Improve removal of dead calls to allocator helpers.
[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) || ((gtCallMoreFlags & GTF_CALL_M_ALLOC_SIDE_EFFECTS) != 0));
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
6729     bool            helperHasSideEffects;
6730     CorInfoHelpFunc helperTemp =
6731         info.compCompHnd->getNewHelper(pResolvedToken, info.compMethodHnd, &helperHasSideEffects);
6732
6733     if (!usingReadyToRunHelper)
6734     {
6735         helper = helperTemp;
6736     }
6737
6738     // TODO: ReadyToRun: When generic dictionary lookups are necessary, replace the lookup call
6739     // and the newfast call with a single call to a dynamic R2R cell that will:
6740     //      1) Load the context
6741     //      2) Perform the generic dictionary lookup and caching, and generate the appropriate stub
6742     //      3) Allocate and return the new object for boxing
6743     // Reason: performance (today, we'll always use the slow helper for the R2R generics case)
6744
6745     GenTreeAllocObj* allocObj =
6746         gtNewAllocObjNode(helper, helperHasSideEffects, pResolvedToken->hClass, TYP_REF, opHandle);
6747
6748 #ifdef FEATURE_READYTORUN_COMPILER
6749     if (usingReadyToRunHelper)
6750     {
6751         allocObj->gtEntryPoint = lookup;
6752     }
6753 #endif
6754
6755     return allocObj;
6756 }
6757
6758 /*****************************************************************************
6759  *
6760  *  Clones the given tree value and returns a copy of the given tree.
6761  *  If 'complexOK' is false, the cloning is only done provided the tree
6762  *     is not too complex (whatever that may mean);
6763  *  If 'complexOK' is true, we try slightly harder to clone the tree.
6764  *  In either case, NULL is returned if the tree cannot be cloned
6765  *
6766  *  Note that there is the function gtCloneExpr() which does a more
6767  *  complete job if you can't handle this function failing.
6768  */
6769
6770 GenTree* Compiler::gtClone(GenTree* tree, bool complexOK)
6771 {
6772     GenTree* copy;
6773
6774     switch (tree->gtOper)
6775     {
6776         case GT_CNS_INT:
6777
6778 #if defined(LATE_DISASM)
6779             if (tree->IsIconHandle())
6780             {
6781                 copy = gtNewIconHandleNode(tree->gtIntCon.gtIconVal, tree->gtFlags, tree->gtIntCon.gtFieldSeq);
6782                 copy->gtIntCon.gtCompileTimeHandle = tree->gtIntCon.gtCompileTimeHandle;
6783                 copy->gtType                       = tree->gtType;
6784             }
6785             else
6786 #endif
6787             {
6788                 copy = new (this, GT_CNS_INT)
6789                     GenTreeIntCon(tree->gtType, tree->gtIntCon.gtIconVal, tree->gtIntCon.gtFieldSeq);
6790                 copy->gtIntCon.gtCompileTimeHandle = tree->gtIntCon.gtCompileTimeHandle;
6791             }
6792             break;
6793
6794         case GT_CNS_LNG:
6795             copy = gtNewLconNode(tree->gtLngCon.gtLconVal);
6796             break;
6797
6798         case GT_LCL_VAR:
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 = gtNewLclvNode(tree->gtLclVarCommon.gtLclNum, tree->gtType, tree->gtLclVar.gtLclILoffs);
6803             break;
6804
6805         case GT_LCL_FLD:
6806         case GT_LCL_FLD_ADDR:
6807             // Remember that the LclVar node has been cloned. The flag will be set
6808             // on 'copy' as well.
6809             tree->gtFlags |= GTF_VAR_CLONED;
6810             copy = new (this, tree->gtOper)
6811                 GenTreeLclFld(tree->gtOper, tree->TypeGet(), tree->gtLclFld.gtLclNum, tree->gtLclFld.gtLclOffs);
6812             copy->gtLclFld.gtFieldSeq = tree->gtLclFld.gtFieldSeq;
6813             break;
6814
6815         case GT_CLS_VAR:
6816             copy = new (this, GT_CLS_VAR)
6817                 GenTreeClsVar(tree->gtType, tree->gtClsVar.gtClsVarHnd, tree->gtClsVar.gtFieldSeq);
6818             break;
6819
6820         default:
6821             if (!complexOK)
6822             {
6823                 return nullptr;
6824             }
6825
6826             if (tree->gtOper == GT_FIELD)
6827             {
6828                 GenTree* objp;
6829
6830                 // copied from line 9850
6831
6832                 objp = nullptr;
6833                 if (tree->gtField.gtFldObj)
6834                 {
6835                     objp = gtClone(tree->gtField.gtFldObj, false);
6836                     if (!objp)
6837                     {
6838                         return objp;
6839                     }
6840                 }
6841
6842                 copy = gtNewFieldRef(tree->TypeGet(), tree->gtField.gtFldHnd, objp, tree->gtField.gtFldOffset);
6843                 copy->gtField.gtFldMayOverlap = tree->gtField.gtFldMayOverlap;
6844 #ifdef FEATURE_READYTORUN_COMPILER
6845                 copy->gtField.gtFieldLookup = tree->gtField.gtFieldLookup;
6846 #endif
6847             }
6848             else if (tree->OperIs(GT_ADD, GT_SUB))
6849             {
6850                 GenTree* op1 = tree->gtOp.gtOp1;
6851                 GenTree* op2 = tree->gtOp.gtOp2;
6852
6853                 if (op1->OperIsLeaf() && op2->OperIsLeaf())
6854                 {
6855                     op1 = gtClone(op1);
6856                     if (op1 == nullptr)
6857                     {
6858                         return nullptr;
6859                     }
6860                     op2 = gtClone(op2);
6861                     if (op2 == nullptr)
6862                     {
6863                         return nullptr;
6864                     }
6865
6866                     copy = gtNewOperNode(tree->OperGet(), tree->TypeGet(), op1, op2);
6867                 }
6868                 else
6869                 {
6870                     return nullptr;
6871                 }
6872             }
6873             else if (tree->gtOper == GT_ADDR)
6874             {
6875                 GenTree* op1 = gtClone(tree->gtOp.gtOp1);
6876                 if (op1 == nullptr)
6877                 {
6878                     return nullptr;
6879                 }
6880                 copy = gtNewOperNode(GT_ADDR, tree->TypeGet(), op1);
6881             }
6882             else
6883             {
6884                 return nullptr;
6885             }
6886
6887             break;
6888     }
6889
6890     copy->gtFlags |= tree->gtFlags & ~GTF_NODE_MASK;
6891 #if defined(DEBUG)
6892     copy->gtDebugFlags |= tree->gtDebugFlags & ~GTF_DEBUG_NODE_MASK;
6893 #endif // defined(DEBUG)
6894
6895     return copy;
6896 }
6897
6898 //------------------------------------------------------------------------
6899 // gtCloneExpr: Create a copy of `tree`, adding flags `addFlags`, mapping
6900 //              local `varNum` to int constant `varVal` if it appears at
6901 //              the root, and mapping uses of local `deepVarNum` to constant
6902 //              `deepVarVal` if they occur beyond the root.
6903 //
6904 // Arguments:
6905 //    tree - GenTree to create a copy of
6906 //    addFlags - GTF_* flags to add to the copied tree nodes
6907 //    varNum - lclNum to replace at the root, or ~0 for no root replacement
6908 //    varVal - If replacing at root, replace local `varNum` with IntCns `varVal`
6909 //    deepVarNum - lclNum to replace uses of beyond the root, or ~0 for no replacement
6910 //    deepVarVal - If replacing beyond root, replace `deepVarNum` with IntCns `deepVarVal`
6911 //
6912 // Return Value:
6913 //    A copy of the given tree with the replacements and added flags specified.
6914 //
6915 // Notes:
6916 //    Top-level callers should generally call the overload that doesn't have
6917 //    the explicit `deepVarNum` and `deepVarVal` parameters; those are used in
6918 //    recursive invocations to avoid replacing defs.
6919
6920 GenTree* Compiler::gtCloneExpr(
6921     GenTree* tree, unsigned addFlags, unsigned varNum, int varVal, unsigned deepVarNum, int deepVarVal)
6922 {
6923     if (tree == nullptr)
6924     {
6925         return nullptr;
6926     }
6927
6928     /* Figure out what kind of a node we have */
6929
6930     genTreeOps oper = tree->OperGet();
6931     unsigned   kind = tree->OperKind();
6932     GenTree*   copy;
6933
6934     /* Is this a constant or leaf node? */
6935
6936     if (kind & (GTK_CONST | GTK_LEAF))
6937     {
6938         switch (oper)
6939         {
6940             case GT_CNS_INT:
6941
6942 #if defined(LATE_DISASM)
6943                 if (tree->IsIconHandle())
6944                 {
6945                     copy = gtNewIconHandleNode(tree->gtIntCon.gtIconVal, tree->gtFlags, tree->gtIntCon.gtFieldSeq);
6946                     copy->gtIntCon.gtCompileTimeHandle = tree->gtIntCon.gtCompileTimeHandle;
6947                     copy->gtType                       = tree->gtType;
6948                 }
6949                 else
6950 #endif
6951                 {
6952                     copy                               = gtNewIconNode(tree->gtIntCon.gtIconVal, tree->gtType);
6953                     copy->gtIntCon.gtCompileTimeHandle = tree->gtIntCon.gtCompileTimeHandle;
6954                     copy->gtIntCon.gtFieldSeq          = tree->gtIntCon.gtFieldSeq;
6955                 }
6956                 goto DONE;
6957
6958             case GT_CNS_LNG:
6959                 copy = gtNewLconNode(tree->gtLngCon.gtLconVal);
6960                 goto DONE;
6961
6962             case GT_CNS_DBL:
6963                 copy         = gtNewDconNode(tree->gtDblCon.gtDconVal);
6964                 copy->gtType = tree->gtType; // keep the same type
6965                 goto DONE;
6966
6967             case GT_CNS_STR:
6968                 copy = gtNewSconNode(tree->gtStrCon.gtSconCPX, tree->gtStrCon.gtScpHnd);
6969                 goto DONE;
6970
6971             case GT_LCL_VAR:
6972
6973                 if (tree->gtLclVarCommon.gtLclNum == varNum)
6974                 {
6975                     copy = gtNewIconNode(varVal, tree->gtType);
6976                     if (tree->gtFlags & GTF_VAR_ARR_INDEX)
6977                     {
6978                         copy->LabelIndex(this);
6979                     }
6980                 }
6981                 else
6982                 {
6983                     // Remember that the LclVar node has been cloned. The flag will
6984                     // be set on 'copy' as well.
6985                     tree->gtFlags |= GTF_VAR_CLONED;
6986                     copy = gtNewLclvNode(tree->gtLclVar.gtLclNum, tree->gtType, tree->gtLclVar.gtLclILoffs);
6987                     copy->AsLclVarCommon()->SetSsaNum(tree->AsLclVarCommon()->GetSsaNum());
6988                 }
6989                 copy->gtFlags = tree->gtFlags;
6990                 goto DONE;
6991
6992             case GT_LCL_FLD:
6993                 if (tree->gtLclFld.gtLclNum == varNum)
6994                 {
6995                     IMPL_LIMITATION("replacing GT_LCL_FLD with a constant");
6996                 }
6997                 else
6998                 {
6999                     // Remember that the LclVar node has been cloned. The flag will
7000                     // be set on 'copy' as well.
7001                     tree->gtFlags |= GTF_VAR_CLONED;
7002                     copy = new (this, GT_LCL_FLD)
7003                         GenTreeLclFld(tree->TypeGet(), tree->gtLclFld.gtLclNum, tree->gtLclFld.gtLclOffs);
7004                     copy->gtLclFld.gtFieldSeq = tree->gtLclFld.gtFieldSeq;
7005                     copy->gtFlags             = tree->gtFlags;
7006                 }
7007                 goto DONE;
7008
7009             case GT_CLS_VAR:
7010                 copy = new (this, GT_CLS_VAR)
7011                     GenTreeClsVar(tree->TypeGet(), tree->gtClsVar.gtClsVarHnd, tree->gtClsVar.gtFieldSeq);
7012                 goto DONE;
7013
7014             case GT_RET_EXPR:
7015                 // GT_RET_EXPR is unique node, that contains a link to a gtInlineCandidate node,
7016                 // that is part of another statement. We cannot clone both here and cannot
7017                 // create another GT_RET_EXPR that points to the same gtInlineCandidate.
7018                 NO_WAY("Cloning of GT_RET_EXPR node not supported");
7019                 goto DONE;
7020
7021             case GT_MEMORYBARRIER:
7022                 copy = new (this, GT_MEMORYBARRIER) GenTree(GT_MEMORYBARRIER, TYP_VOID);
7023                 goto DONE;
7024
7025             case GT_ARGPLACE:
7026                 copy = gtNewArgPlaceHolderNode(tree->gtType, tree->gtArgPlace.gtArgPlaceClsHnd);
7027                 goto DONE;
7028
7029             case GT_FTN_ADDR:
7030                 copy = new (this, oper) GenTreeFptrVal(tree->gtType, tree->gtFptrVal.gtFptrMethod);
7031
7032 #ifdef FEATURE_READYTORUN_COMPILER
7033                 copy->gtFptrVal.gtEntryPoint = tree->gtFptrVal.gtEntryPoint;
7034 #endif
7035                 goto DONE;
7036
7037             case GT_CATCH_ARG:
7038             case GT_NO_OP:
7039                 copy = new (this, oper) GenTree(oper, tree->gtType);
7040                 goto DONE;
7041
7042 #if !FEATURE_EH_FUNCLETS
7043             case GT_END_LFIN:
7044 #endif // !FEATURE_EH_FUNCLETS
7045             case GT_JMP:
7046                 copy = new (this, oper) GenTreeVal(oper, tree->gtType, tree->gtVal.gtVal1);
7047                 goto DONE;
7048
7049             case GT_LABEL:
7050                 copy = new (this, oper) GenTreeLabel(tree->gtLabel.gtLabBB);
7051                 goto DONE;
7052
7053             default:
7054                 NO_WAY("Cloning of node not supported");
7055                 goto DONE;
7056         }
7057     }
7058
7059     /* Is it a 'simple' unary/binary operator? */
7060
7061     if (kind & GTK_SMPOP)
7062     {
7063         /* If necessary, make sure we allocate a "fat" tree node */
7064         CLANG_FORMAT_COMMENT_ANCHOR;
7065
7066 #if SMALL_TREE_NODES
7067         switch (oper)
7068         {
7069             /* These nodes sometimes get bashed to "fat" ones */
7070
7071             case GT_MUL:
7072             case GT_DIV:
7073             case GT_MOD:
7074
7075             case GT_UDIV:
7076             case GT_UMOD:
7077
7078                 //  In the implementation of gtNewLargeOperNode you have
7079                 //  to give an oper that will create a small node,
7080                 //  otherwise it asserts.
7081                 //
7082                 if (GenTree::s_gtNodeSizes[oper] == TREE_NODE_SZ_SMALL)
7083                 {
7084                     copy = gtNewLargeOperNode(oper, tree->TypeGet(), tree->gtOp.gtOp1,
7085                                               tree->OperIsBinary() ? tree->gtOp.gtOp2 : nullptr);
7086                 }
7087                 else // Always a large tree
7088                 {
7089                     if (tree->OperIsBinary())
7090                     {
7091                         copy = gtNewOperNode(oper, tree->TypeGet(), tree->gtOp.gtOp1, tree->gtOp.gtOp2);
7092                     }
7093                     else
7094                     {
7095                         copy = gtNewOperNode(oper, tree->TypeGet(), tree->gtOp.gtOp1);
7096                     }
7097                 }
7098                 break;
7099
7100             case GT_CAST:
7101                 copy =
7102                     new (this, LargeOpOpcode()) GenTreeCast(tree->TypeGet(), tree->gtCast.CastOp(), tree->IsUnsigned(),
7103                                                             tree->gtCast.gtCastType DEBUGARG(/*largeNode*/ TRUE));
7104                 break;
7105
7106             // The nodes below this are not bashed, so they can be allocated at their individual sizes.
7107
7108             case GT_LIST:
7109                 assert((tree->gtOp.gtOp2 == nullptr) || tree->gtOp.gtOp2->OperIsList());
7110                 copy             = new (this, GT_LIST) GenTreeArgList(tree->gtOp.gtOp1);
7111                 copy->gtOp.gtOp2 = tree->gtOp.gtOp2;
7112                 break;
7113
7114             case GT_FIELD_LIST:
7115                 copy = new (this, GT_FIELD_LIST) GenTreeFieldList(tree->gtOp.gtOp1, tree->AsFieldList()->gtFieldOffset,
7116                                                                   tree->AsFieldList()->gtFieldType, nullptr);
7117                 copy->gtOp.gtOp2 = tree->gtOp.gtOp2;
7118                 copy->gtFlags    = (copy->gtFlags & ~GTF_FIELD_LIST_HEAD) | (tree->gtFlags & GTF_FIELD_LIST_HEAD);
7119                 break;
7120
7121             case GT_INDEX:
7122             {
7123                 GenTreeIndex* asInd = tree->AsIndex();
7124                 copy                = new (this, GT_INDEX)
7125                     GenTreeIndex(asInd->TypeGet(), asInd->Arr(), asInd->Index(), asInd->gtIndElemSize);
7126                 copy->AsIndex()->gtStructElemClass = asInd->gtStructElemClass;
7127             }
7128             break;
7129
7130             case GT_INDEX_ADDR:
7131             {
7132                 GenTreeIndexAddr* asIndAddr = tree->AsIndexAddr();
7133
7134                 copy = new (this, GT_INDEX_ADDR)
7135                     GenTreeIndexAddr(asIndAddr->Arr(), asIndAddr->Index(), asIndAddr->gtElemType,
7136                                      asIndAddr->gtStructElemClass, asIndAddr->gtElemSize, asIndAddr->gtLenOffset,
7137                                      asIndAddr->gtElemOffset);
7138                 copy->AsIndexAddr()->gtIndRngFailBB = asIndAddr->gtIndRngFailBB;
7139             }
7140             break;
7141
7142             case GT_ALLOCOBJ:
7143             {
7144                 GenTreeAllocObj* asAllocObj = tree->AsAllocObj();
7145                 copy                        = new (this, GT_ALLOCOBJ)
7146                     GenTreeAllocObj(tree->TypeGet(), asAllocObj->gtNewHelper, asAllocObj->gtHelperHasSideEffects,
7147                                     asAllocObj->gtAllocObjClsHnd, asAllocObj->gtOp1);
7148             }
7149             break;
7150
7151             case GT_RUNTIMELOOKUP:
7152             {
7153                 GenTreeRuntimeLookup* asRuntimeLookup = tree->AsRuntimeLookup();
7154
7155                 copy = new (this, GT_RUNTIMELOOKUP)
7156                     GenTreeRuntimeLookup(asRuntimeLookup->gtHnd, asRuntimeLookup->gtHndType, asRuntimeLookup->gtOp1);
7157             }
7158             break;
7159
7160             case GT_ARR_LENGTH:
7161                 copy = gtNewArrLen(tree->TypeGet(), tree->gtOp.gtOp1, tree->gtArrLen.ArrLenOffset());
7162                 break;
7163
7164             case GT_ARR_INDEX:
7165                 copy = new (this, GT_ARR_INDEX)
7166                     GenTreeArrIndex(tree->TypeGet(),
7167                                     gtCloneExpr(tree->gtArrIndex.ArrObj(), addFlags, deepVarNum, deepVarVal),
7168                                     gtCloneExpr(tree->gtArrIndex.IndexExpr(), addFlags, deepVarNum, deepVarVal),
7169                                     tree->gtArrIndex.gtCurrDim, tree->gtArrIndex.gtArrRank,
7170                                     tree->gtArrIndex.gtArrElemType);
7171                 break;
7172
7173             case GT_QMARK:
7174                 copy = new (this, GT_QMARK) GenTreeQmark(tree->TypeGet(), tree->gtOp.gtOp1, tree->gtOp.gtOp2, this);
7175                 break;
7176
7177             case GT_OBJ:
7178                 copy = new (this, GT_OBJ)
7179                     GenTreeObj(tree->TypeGet(), tree->gtOp.gtOp1, tree->AsObj()->gtClass, tree->gtBlk.gtBlkSize);
7180                 copy->AsObj()->CopyGCInfo(tree->AsObj());
7181                 copy->gtBlk.gtBlkOpGcUnsafe = tree->gtBlk.gtBlkOpGcUnsafe;
7182                 break;
7183
7184             case GT_BLK:
7185                 copy = new (this, GT_BLK) GenTreeBlk(GT_BLK, tree->TypeGet(), tree->gtOp.gtOp1, tree->gtBlk.gtBlkSize);
7186                 copy->gtBlk.gtBlkOpGcUnsafe = tree->gtBlk.gtBlkOpGcUnsafe;
7187                 break;
7188
7189             case GT_DYN_BLK:
7190                 copy = new (this, GT_DYN_BLK) GenTreeDynBlk(tree->gtOp.gtOp1, tree->gtDynBlk.gtDynamicSize);
7191                 copy->gtBlk.gtBlkOpGcUnsafe = tree->gtBlk.gtBlkOpGcUnsafe;
7192                 break;
7193
7194             case GT_BOX:
7195                 copy = new (this, GT_BOX)
7196                     GenTreeBox(tree->TypeGet(), tree->gtOp.gtOp1, tree->gtBox.gtAsgStmtWhenInlinedBoxValue,
7197                                tree->gtBox.gtCopyStmtWhenInlinedBoxValue);
7198                 break;
7199
7200             case GT_INTRINSIC:
7201                 copy = new (this, GT_INTRINSIC)
7202                     GenTreeIntrinsic(tree->TypeGet(), tree->gtOp.gtOp1, tree->gtOp.gtOp2,
7203                                      tree->gtIntrinsic.gtIntrinsicId, tree->gtIntrinsic.gtMethodHandle);
7204 #ifdef FEATURE_READYTORUN_COMPILER
7205                 copy->gtIntrinsic.gtEntryPoint = tree->gtIntrinsic.gtEntryPoint;
7206 #endif
7207                 break;
7208
7209             case GT_LEA:
7210             {
7211                 GenTreeAddrMode* addrModeOp = tree->AsAddrMode();
7212                 copy                        = new (this, GT_LEA)
7213                     GenTreeAddrMode(addrModeOp->TypeGet(), addrModeOp->Base(), addrModeOp->Index(), addrModeOp->gtScale,
7214                                     static_cast<unsigned>(addrModeOp->Offset()));
7215             }
7216             break;
7217
7218             case GT_COPY:
7219             case GT_RELOAD:
7220             {
7221                 copy = new (this, oper) GenTreeCopyOrReload(oper, tree->TypeGet(), tree->gtGetOp1());
7222             }
7223             break;
7224
7225 #ifdef FEATURE_SIMD
7226             case GT_SIMD:
7227             {
7228                 GenTreeSIMD* simdOp = tree->AsSIMD();
7229                 copy                = gtNewSIMDNode(simdOp->TypeGet(), simdOp->gtGetOp1(), simdOp->gtGetOp2IfPresent(),
7230                                      simdOp->gtSIMDIntrinsicID, simdOp->gtSIMDBaseType, simdOp->gtSIMDSize);
7231             }
7232             break;
7233 #endif
7234
7235 #ifdef FEATURE_HW_INTRINSICS
7236             case GT_HWIntrinsic:
7237             {
7238                 GenTreeHWIntrinsic* hwintrinsicOp = tree->AsHWIntrinsic();
7239                 copy                              = new (this, GT_HWIntrinsic)
7240                     GenTreeHWIntrinsic(hwintrinsicOp->TypeGet(), hwintrinsicOp->gtGetOp1(),
7241                                        hwintrinsicOp->gtGetOp2IfPresent(), hwintrinsicOp->gtHWIntrinsicId,
7242                                        hwintrinsicOp->gtSIMDBaseType, hwintrinsicOp->gtSIMDSize);
7243                 copy->AsHWIntrinsic()->gtIndexBaseType = hwintrinsicOp->gtIndexBaseType;
7244             }
7245             break;
7246 #endif
7247
7248             default:
7249                 assert(!GenTree::IsExOp(tree->OperKind()) && tree->OperIsSimple());
7250                 // We're in the SimpleOp case, so it's always unary or binary.
7251                 if (GenTree::OperIsUnary(tree->OperGet()))
7252                 {
7253                     copy = gtNewOperNode(oper, tree->TypeGet(), tree->gtOp.gtOp1, /*doSimplifications*/ false);
7254                 }
7255                 else
7256                 {
7257                     assert(GenTree::OperIsBinary(tree->OperGet()));
7258                     copy = gtNewOperNode(oper, tree->TypeGet(), tree->gtOp.gtOp1, tree->gtOp.gtOp2);
7259                 }
7260                 break;
7261         }
7262 #else
7263         // We're in the SimpleOp case, so it's always unary or binary.
7264         copy = gtNewOperNode(oper, tree->TypeGet(), tree->gtOp.gtOp1, tree->gtOp.gtOp2);
7265 #endif
7266
7267         // Some flags are conceptually part of the gtOper, and should be copied immediately.
7268         if (tree->gtOverflowEx())
7269         {
7270             copy->gtFlags |= GTF_OVERFLOW;
7271         }
7272
7273         if (tree->gtOp.gtOp1)
7274         {
7275             if (tree->gtOper == GT_ASG)
7276             {
7277                 // Don't replace varNum if it appears as the LHS of an assign.
7278                 copy->gtOp.gtOp1 = gtCloneExpr(tree->gtOp.gtOp1, addFlags, -1, 0, deepVarNum, deepVarVal);
7279             }
7280             else
7281             {
7282                 copy->gtOp.gtOp1 = gtCloneExpr(tree->gtOp.gtOp1, addFlags, deepVarNum, deepVarVal);
7283             }
7284         }
7285
7286         if (tree->gtGetOp2IfPresent())
7287         {
7288             copy->gtOp.gtOp2 = gtCloneExpr(tree->gtOp.gtOp2, addFlags, deepVarNum, deepVarVal);
7289         }
7290
7291         /* Flags */
7292         addFlags |= tree->gtFlags;
7293
7294         // Copy any node annotations, if necessary.
7295         switch (tree->gtOper)
7296         {
7297             case GT_STOREIND:
7298             case GT_IND:
7299             case GT_OBJ:
7300             case GT_STORE_OBJ:
7301             {
7302                 ArrayInfo arrInfo;
7303                 if (!tree->AsIndir()->gtOp1->OperIs(GT_INDEX_ADDR) && TryGetArrayInfo(tree->AsIndir(), &arrInfo))
7304                 {
7305                     GetArrayInfoMap()->Set(copy, arrInfo);
7306                 }
7307             }
7308             break;
7309
7310             default:
7311                 break;
7312         }
7313
7314 #ifdef DEBUG
7315         /* GTF_NODE_MASK should not be propagated from 'tree' to 'copy' */
7316         addFlags &= ~GTF_NODE_MASK;
7317 #endif
7318
7319         // Effects flags propagate upwards.
7320         if (copy->gtOp.gtOp1 != nullptr)
7321         {
7322             copy->gtFlags |= (copy->gtOp.gtOp1->gtFlags & GTF_ALL_EFFECT);
7323         }
7324         if (copy->gtGetOp2IfPresent() != nullptr)
7325         {
7326             copy->gtFlags |= (copy->gtGetOp2()->gtFlags & GTF_ALL_EFFECT);
7327         }
7328
7329         goto DONE;
7330     }
7331
7332     /* See what kind of a special operator we have here */
7333
7334     switch (oper)
7335     {
7336         case GT_STMT:
7337             copy = gtCloneExpr(tree->gtStmt.gtStmtExpr, addFlags, deepVarNum, deepVarVal);
7338             copy = gtNewStmt(copy, tree->gtStmt.gtStmtILoffsx);
7339             goto DONE;
7340
7341         case GT_CALL:
7342
7343             // We can't safely clone calls that have GT_RET_EXPRs via gtCloneExpr.
7344             // You must use gtCloneCandidateCall for these calls (and then do appropriate other fixup)
7345             if (tree->gtCall.IsInlineCandidate() || tree->gtCall.IsGuardedDevirtualizationCandidate())
7346             {
7347                 NO_WAY("Cloning of calls with associated GT_RET_EXPR nodes is not supported");
7348             }
7349
7350             copy = gtCloneExprCallHelper(tree->AsCall(), addFlags, deepVarNum, deepVarVal);
7351             break;
7352
7353         case GT_FIELD:
7354
7355             copy = gtNewFieldRef(tree->TypeGet(), tree->gtField.gtFldHnd, nullptr, tree->gtField.gtFldOffset);
7356
7357             copy->gtField.gtFldObj = tree->gtField.gtFldObj
7358                                          ? gtCloneExpr(tree->gtField.gtFldObj, addFlags, deepVarNum, deepVarVal)
7359                                          : nullptr;
7360             copy->gtField.gtFldMayOverlap = tree->gtField.gtFldMayOverlap;
7361 #ifdef FEATURE_READYTORUN_COMPILER
7362             copy->gtField.gtFieldLookup = tree->gtField.gtFieldLookup;
7363 #endif
7364
7365             break;
7366
7367         case GT_ARR_ELEM:
7368         {
7369             GenTree* inds[GT_ARR_MAX_RANK];
7370             for (unsigned dim = 0; dim < tree->gtArrElem.gtArrRank; dim++)
7371             {
7372                 inds[dim] = gtCloneExpr(tree->gtArrElem.gtArrInds[dim], addFlags, deepVarNum, deepVarVal);
7373             }
7374             copy = new (this, GT_ARR_ELEM)
7375                 GenTreeArrElem(tree->TypeGet(), gtCloneExpr(tree->gtArrElem.gtArrObj, addFlags, deepVarNum, deepVarVal),
7376                                tree->gtArrElem.gtArrRank, tree->gtArrElem.gtArrElemSize, tree->gtArrElem.gtArrElemType,
7377                                &inds[0]);
7378         }
7379         break;
7380
7381         case GT_ARR_OFFSET:
7382         {
7383             copy = new (this, GT_ARR_OFFSET)
7384                 GenTreeArrOffs(tree->TypeGet(), gtCloneExpr(tree->gtArrOffs.gtOffset, addFlags, deepVarNum, deepVarVal),
7385                                gtCloneExpr(tree->gtArrOffs.gtIndex, addFlags, deepVarNum, deepVarVal),
7386                                gtCloneExpr(tree->gtArrOffs.gtArrObj, addFlags, deepVarNum, deepVarVal),
7387                                tree->gtArrOffs.gtCurrDim, tree->gtArrOffs.gtArrRank, tree->gtArrOffs.gtArrElemType);
7388         }
7389         break;
7390
7391         case GT_CMPXCHG:
7392             copy = new (this, GT_CMPXCHG)
7393                 GenTreeCmpXchg(tree->TypeGet(),
7394                                gtCloneExpr(tree->gtCmpXchg.gtOpLocation, addFlags, deepVarNum, deepVarVal),
7395                                gtCloneExpr(tree->gtCmpXchg.gtOpValue, addFlags, deepVarNum, deepVarVal),
7396                                gtCloneExpr(tree->gtCmpXchg.gtOpComparand, addFlags, deepVarNum, deepVarVal));
7397             break;
7398
7399         case GT_ARR_BOUNDS_CHECK:
7400 #ifdef FEATURE_SIMD
7401         case GT_SIMD_CHK:
7402 #endif // FEATURE_SIMD
7403 #ifdef FEATURE_HW_INTRINSICS
7404         case GT_HW_INTRINSIC_CHK:
7405 #endif // FEATURE_HW_INTRINSICS
7406             copy = new (this, oper)
7407                 GenTreeBoundsChk(oper, tree->TypeGet(),
7408                                  gtCloneExpr(tree->gtBoundsChk.gtIndex, addFlags, deepVarNum, deepVarVal),
7409                                  gtCloneExpr(tree->gtBoundsChk.gtArrLen, addFlags, deepVarNum, deepVarVal),
7410                                  tree->gtBoundsChk.gtThrowKind);
7411             copy->gtBoundsChk.gtIndRngFailBB = tree->gtBoundsChk.gtIndRngFailBB;
7412             break;
7413
7414         case GT_STORE_DYN_BLK:
7415         case GT_DYN_BLK:
7416             copy = new (this, oper)
7417                 GenTreeDynBlk(gtCloneExpr(tree->gtDynBlk.Addr(), addFlags, deepVarNum, deepVarVal),
7418                               gtCloneExpr(tree->gtDynBlk.gtDynamicSize, addFlags, deepVarNum, deepVarVal));
7419             break;
7420
7421         default:
7422 #ifdef DEBUG
7423             gtDispTree(tree);
7424 #endif
7425             NO_WAY("unexpected operator");
7426     }
7427
7428 DONE:
7429
7430     // If it has a zero-offset field seq, copy annotation.
7431     if (tree->TypeGet() == TYP_BYREF)
7432     {
7433         FieldSeqNode* fldSeq = nullptr;
7434         if (GetZeroOffsetFieldMap()->Lookup(tree, &fldSeq))
7435         {
7436             GetZeroOffsetFieldMap()->Set(copy, fldSeq);
7437         }
7438     }
7439
7440     copy->gtVNPair = tree->gtVNPair; // A cloned tree gets the orginal's Value number pair
7441
7442     /* Compute the flags for the copied node. Note that we can do this only
7443        if we didnt gtFoldExpr(copy) */
7444
7445     if (copy->gtOper == oper)
7446     {
7447         addFlags |= tree->gtFlags;
7448
7449 #ifdef DEBUG
7450         /* GTF_NODE_MASK should not be propagated from 'tree' to 'copy' */
7451         addFlags &= ~GTF_NODE_MASK;
7452 #endif
7453         // Some other flags depend on the context of the expression, and should not be preserved.
7454         // For example, GTF_RELOP_QMARK:
7455         if (copy->OperKind() & GTK_RELOP)
7456         {
7457             addFlags &= ~GTF_RELOP_QMARK;
7458         }
7459         // On the other hand, if we're creating such a context, restore this flag.
7460         if (copy->OperGet() == GT_QMARK)
7461         {
7462             copy->gtOp.gtOp1->gtFlags |= GTF_RELOP_QMARK;
7463         }
7464
7465         copy->gtFlags |= addFlags;
7466
7467         // Update side effect flags since they may be different from the source side effect flags.
7468         // For example, we may have replaced some locals with constants and made indirections non-throwing.
7469         gtUpdateNodeSideEffects(copy);
7470     }
7471
7472     /* GTF_COLON_COND should be propagated from 'tree' to 'copy' */
7473     copy->gtFlags |= (tree->gtFlags & GTF_COLON_COND);
7474
7475 #if defined(DEBUG)
7476     // Non-node debug flags should be propagated from 'tree' to 'copy'
7477     copy->gtDebugFlags |= (tree->gtDebugFlags & ~GTF_DEBUG_NODE_MASK);
7478 #endif
7479
7480     /* Make sure to copy back fields that may have been initialized */
7481
7482     copy->CopyRawCosts(tree);
7483     copy->gtRsvdRegs = tree->gtRsvdRegs;
7484     copy->CopyReg(tree);
7485     return copy;
7486 }
7487
7488 //------------------------------------------------------------------------
7489 // gtCloneExprCallHelper: clone a call tree
7490 //
7491 // Notes:
7492 //    Do not invoke this method directly, instead call either gtCloneExpr
7493 //    or gtCloneCandidateCall, as appropriate.
7494 //
7495 // Arguments:
7496 //    tree - the call to clone
7497 //    addFlags - GTF_* flags to add to the copied tree nodes
7498 //    deepVarNum - lclNum to replace uses of beyond the root, or BAD_VAR_NUM for no replacement
7499 //    deepVarVal - If replacing beyond root, replace `deepVarNum` with IntCns `deepVarVal`
7500 //
7501 // Returns:
7502 //    Cloned copy of call and all subtrees.
7503
7504 GenTreeCall* Compiler::gtCloneExprCallHelper(GenTreeCall* tree, unsigned addFlags, unsigned deepVarNum, int deepVarVal)
7505 {
7506     GenTreeCall* copy = new (this, GT_CALL) GenTreeCall(tree->TypeGet());
7507
7508     copy->gtCallObjp = tree->gtCallObjp ? gtCloneExpr(tree->gtCallObjp, addFlags, deepVarNum, deepVarVal) : nullptr;
7509     copy->gtCallArgs =
7510         tree->gtCallArgs ? gtCloneExpr(tree->gtCallArgs, addFlags, deepVarNum, deepVarVal)->AsArgList() : nullptr;
7511     copy->gtCallMoreFlags = tree->gtCallMoreFlags;
7512     copy->gtCallLateArgs  = tree->gtCallLateArgs
7513                                ? gtCloneExpr(tree->gtCallLateArgs, addFlags, deepVarNum, deepVarVal)->AsArgList()
7514                                : nullptr;
7515
7516 #if !FEATURE_FIXED_OUT_ARGS
7517     copy->regArgList      = tree->regArgList;
7518     copy->regArgListCount = tree->regArgListCount;
7519 #endif
7520
7521     // The call sig comes from the EE and doesn't change throughout the compilation process, meaning
7522     // we only really need one physical copy of it. Therefore a shallow pointer copy will suffice.
7523     // (Note that this still holds even if the tree we are cloning was created by an inlinee compiler,
7524     // because the inlinee still uses the inliner's memory allocator anyway.)
7525     copy->callSig = tree->callSig;
7526
7527     copy->gtCallType    = tree->gtCallType;
7528     copy->gtReturnType  = tree->gtReturnType;
7529     copy->gtControlExpr = tree->gtControlExpr;
7530
7531     /* Copy the union */
7532     if (tree->gtCallType == CT_INDIRECT)
7533     {
7534         copy->gtCallCookie =
7535             tree->gtCallCookie ? gtCloneExpr(tree->gtCallCookie, addFlags, deepVarNum, deepVarVal) : nullptr;
7536         copy->gtCallAddr = tree->gtCallAddr ? gtCloneExpr(tree->gtCallAddr, addFlags, deepVarNum, deepVarVal) : nullptr;
7537     }
7538     else if (tree->IsVirtualStub())
7539     {
7540         copy->gtCallMethHnd      = tree->gtCallMethHnd;
7541         copy->gtStubCallStubAddr = tree->gtStubCallStubAddr;
7542     }
7543     else
7544     {
7545         copy->gtCallMethHnd         = tree->gtCallMethHnd;
7546         copy->gtInlineCandidateInfo = nullptr;
7547     }
7548
7549     if (tree->fgArgInfo)
7550     {
7551         // Create and initialize the fgArgInfo for our copy of the call tree
7552         copy->fgArgInfo = new (this, CMK_Unknown) fgArgInfo(copy, tree);
7553     }
7554     else
7555     {
7556         copy->fgArgInfo = nullptr;
7557     }
7558
7559     copy->gtRetClsHnd = tree->gtRetClsHnd;
7560
7561 #if FEATURE_MULTIREG_RET
7562     copy->gtReturnTypeDesc = tree->gtReturnTypeDesc;
7563 #endif
7564
7565 #ifdef FEATURE_READYTORUN_COMPILER
7566     copy->setEntryPoint(tree->gtEntryPoint);
7567 #endif
7568
7569 #if defined(DEBUG) || defined(INLINE_DATA)
7570     copy->gtInlineObservation = tree->gtInlineObservation;
7571     copy->gtRawILOffset       = tree->gtCall.gtRawILOffset;
7572 #endif
7573
7574     copy->CopyOtherRegFlags(tree);
7575
7576     return copy;
7577 }
7578
7579 //------------------------------------------------------------------------
7580 // gtCloneCandidateCall: clone a call that is an inline or guarded
7581 //    devirtualization candidate (~ any call that can have a GT_RET_EXPR)
7582 //
7583 // Notes:
7584 //    If the call really is a candidate, the caller must take additional steps
7585 //    after cloning to re-establish candidate info and the relationship between
7586 //    the candidate and any associated GT_RET_EXPR.
7587 //
7588 // Arguments:
7589 //    call - the call to clone
7590 //
7591 // Returns:
7592 //    Cloned copy of call and all subtrees.
7593
7594 GenTreeCall* Compiler::gtCloneCandidateCall(GenTreeCall* call)
7595 {
7596     assert(call->IsInlineCandidate() || call->IsGuardedDevirtualizationCandidate());
7597
7598     GenTreeCall* result = gtCloneExprCallHelper(call);
7599
7600     // There is some common post-processing in gtCloneExpr that we reproduce
7601     // here, for the fields that make sense for candidate calls.
7602     result->gtFlags |= call->gtFlags;
7603
7604 #if defined(DEBUG)
7605     result->gtDebugFlags |= (call->gtDebugFlags & ~GTF_DEBUG_NODE_MASK);
7606 #endif
7607
7608     result->CopyReg(call);
7609
7610     return result;
7611 }
7612
7613 //------------------------------------------------------------------------
7614 // gtReplaceTree: Replace a tree with a new tree.
7615 //
7616 // Arguments:
7617 //    stmt            - The top-level root stmt of the tree being replaced.
7618 //                      Must not be null.
7619 //    tree            - The tree being replaced. Must not be null.
7620 //    replacementTree - The replacement tree. Must not be null.
7621 //
7622 // Return Value:
7623 //    The tree node that replaces the old tree.
7624 //
7625 // Assumptions:
7626 //    The sequencing of the stmt has been done.
7627 //
7628 // Notes:
7629 //    The caller must ensure that the original statement has been sequenced,
7630 //    and the side effect flags are updated on the statement nodes,
7631 //    but this method will sequence 'replacementTree', and insert it into the
7632 //    proper place in the statement sequence.
7633
7634 GenTree* Compiler::gtReplaceTree(GenTree* stmt, GenTree* tree, GenTree* replacementTree)
7635 {
7636     assert(fgStmtListThreaded);
7637     assert(tree != nullptr);
7638     assert(stmt != nullptr);
7639     assert(replacementTree != nullptr);
7640
7641     GenTree** treePtr    = nullptr;
7642     GenTree*  treeParent = tree->gtGetParent(&treePtr);
7643
7644     assert(treeParent != nullptr || tree == stmt->gtStmt.gtStmtExpr);
7645
7646     if (treePtr == nullptr)
7647     {
7648         // Replace the stmt expr and rebuild the linear order for "stmt".
7649         assert(treeParent == nullptr);
7650         assert(fgOrder != FGOrderLinear);
7651         stmt->gtStmt.gtStmtExpr = tree;
7652         fgSetStmtSeq(stmt);
7653     }
7654     else
7655     {
7656         assert(treeParent != nullptr);
7657
7658         // Check to see if the node to be replaced is a call argument and if so,
7659         // set `treeParent` to the call node.
7660         GenTree* cursor = treeParent;
7661         while ((cursor != nullptr) && (cursor->OperGet() == GT_LIST))
7662         {
7663             cursor = cursor->gtNext;
7664         }
7665
7666         if ((cursor != nullptr) && (cursor->OperGet() == GT_CALL))
7667         {
7668             treeParent = cursor;
7669         }
7670
7671 #ifdef DEBUG
7672         GenTree** useEdge;
7673         assert(treeParent->TryGetUse(tree, &useEdge));
7674         assert(useEdge == treePtr);
7675 #endif // DEBUG
7676
7677         GenTree* treeFirstNode = fgGetFirstNode(tree);
7678         GenTree* treeLastNode  = tree;
7679         GenTree* treePrevNode  = treeFirstNode->gtPrev;
7680         GenTree* treeNextNode  = treeLastNode->gtNext;
7681
7682         treeParent->ReplaceOperand(treePtr, replacementTree);
7683
7684         // Build the linear order for "replacementTree".
7685         fgSetTreeSeq(replacementTree, treePrevNode);
7686
7687         // Restore linear-order Prev and Next for "replacementTree".
7688         if (treePrevNode != nullptr)
7689         {
7690             treeFirstNode         = fgGetFirstNode(replacementTree);
7691             treeFirstNode->gtPrev = treePrevNode;
7692             treePrevNode->gtNext  = treeFirstNode;
7693         }
7694         else
7695         {
7696             // Update the linear oder start of "stmt" if treeFirstNode
7697             // appears to have replaced the original first node.
7698             assert(treeFirstNode == stmt->gtStmt.gtStmtList);
7699             stmt->gtStmt.gtStmtList = fgGetFirstNode(replacementTree);
7700         }
7701
7702         if (treeNextNode != nullptr)
7703         {
7704             treeLastNode         = replacementTree;
7705             treeLastNode->gtNext = treeNextNode;
7706             treeNextNode->gtPrev = treeLastNode;
7707         }
7708     }
7709
7710     return replacementTree;
7711 }
7712
7713 //------------------------------------------------------------------------
7714 // gtUpdateSideEffects: Update the side effects of a tree and its ancestors
7715 //
7716 // Arguments:
7717 //    stmt            - The tree's statement
7718 //    tree            - Tree to update the side effects for
7719 //
7720 // Note: If tree's order hasn't been established, the method updates side effect
7721 //       flags on all statement's nodes.
7722
7723 void Compiler::gtUpdateSideEffects(GenTree* stmt, GenTree* tree)
7724 {
7725     if (fgStmtListThreaded)
7726     {
7727         gtUpdateTreeAncestorsSideEffects(tree);
7728     }
7729     else
7730     {
7731         gtUpdateStmtSideEffects(stmt);
7732     }
7733 }
7734
7735 //------------------------------------------------------------------------
7736 // gtUpdateTreeAncestorsSideEffects: Update the side effects of a tree and its ancestors
7737 //                                   when statement order has been established.
7738 //
7739 // Arguments:
7740 //    tree            - Tree to update the side effects for
7741
7742 void Compiler::gtUpdateTreeAncestorsSideEffects(GenTree* tree)
7743 {
7744     assert(fgStmtListThreaded);
7745     while (tree != nullptr)
7746     {
7747         gtUpdateNodeSideEffects(tree);
7748         tree = tree->gtGetParent(nullptr);
7749     }
7750 }
7751
7752 //------------------------------------------------------------------------
7753 // gtUpdateStmtSideEffects: Update the side effects for statement tree nodes.
7754 //
7755 // Arguments:
7756 //    stmt            - The statement to update side effects on
7757
7758 void Compiler::gtUpdateStmtSideEffects(GenTree* stmt)
7759 {
7760     fgWalkTree(&stmt->gtStmt.gtStmtExpr, fgUpdateSideEffectsPre, fgUpdateSideEffectsPost);
7761 }
7762
7763 //------------------------------------------------------------------------
7764 // gtUpdateNodeOperSideEffects: Update the side effects based on the node operation.
7765 //
7766 // Arguments:
7767 //    tree            - Tree to update the side effects on
7768 //
7769 // Notes:
7770 //    This method currently only updates GTF_EXCEPT, GTF_ASG, and GTF_CALL flags.
7771 //    The other side effect flags may remain unnecessarily (conservatively) set.
7772 //    The caller of this method is expected to update the flags based on the children's flags.
7773
7774 void Compiler::gtUpdateNodeOperSideEffects(GenTree* tree)
7775 {
7776     if (tree->OperMayThrow(this))
7777     {
7778         tree->gtFlags |= GTF_EXCEPT;
7779     }
7780     else
7781     {
7782         tree->gtFlags &= ~GTF_EXCEPT;
7783         if (tree->OperIsIndirOrArrLength())
7784         {
7785             tree->gtFlags |= GTF_IND_NONFAULTING;
7786         }
7787     }
7788
7789     if (tree->OperRequiresAsgFlag())
7790     {
7791         tree->gtFlags |= GTF_ASG;
7792     }
7793     else
7794     {
7795         tree->gtFlags &= ~GTF_ASG;
7796     }
7797
7798     if (tree->OperRequiresCallFlag(this))
7799     {
7800         tree->gtFlags |= GTF_CALL;
7801     }
7802     else
7803     {
7804         tree->gtFlags &= ~GTF_CALL;
7805     }
7806 }
7807
7808 //------------------------------------------------------------------------
7809 // gtUpdateNodeSideEffects: Update the side effects based on the node operation and
7810 //                          children's side efects.
7811 //
7812 // Arguments:
7813 //    tree            - Tree to update the side effects on
7814 //
7815 // Notes:
7816 //    This method currently only updates GTF_EXCEPT and GTF_ASG flags. The other side effect
7817 //    flags may remain unnecessarily (conservatively) set.
7818
7819 void Compiler::gtUpdateNodeSideEffects(GenTree* tree)
7820 {
7821     gtUpdateNodeOperSideEffects(tree);
7822     unsigned nChildren = tree->NumChildren();
7823     for (unsigned childNum = 0; childNum < nChildren; childNum++)
7824     {
7825         GenTree* child = tree->GetChild(childNum);
7826         if (child != nullptr)
7827         {
7828             tree->gtFlags |= (child->gtFlags & GTF_ALL_EFFECT);
7829         }
7830     }
7831 }
7832
7833 //------------------------------------------------------------------------
7834 // fgUpdateSideEffectsPre: Update the side effects based on the tree operation.
7835 //
7836 // Arguments:
7837 //    pTree            - Pointer to the tree to update the side effects
7838 //    fgWalkPre        - Walk data
7839 //
7840 // Notes:
7841 //    This method currently only updates GTF_EXCEPT and GTF_ASG flags. The other side effect
7842 //    flags may remain unnecessarily (conservatively) set.
7843
7844 Compiler::fgWalkResult Compiler::fgUpdateSideEffectsPre(GenTree** pTree, fgWalkData* fgWalkPre)
7845 {
7846     fgWalkPre->compiler->gtUpdateNodeOperSideEffects(*pTree);
7847
7848     return WALK_CONTINUE;
7849 }
7850
7851 //------------------------------------------------------------------------
7852 // fgUpdateSideEffectsPost: Update the side effects of the parent based on the tree's flags.
7853 //
7854 // Arguments:
7855 //    pTree            - Pointer to the tree
7856 //    fgWalkPost       - Walk data
7857 //
7858 // Notes:
7859 //    The routine is used for updating the stale side effect flags for ancestor
7860 //    nodes starting from treeParent up to the top-level stmt expr.
7861
7862 Compiler::fgWalkResult Compiler::fgUpdateSideEffectsPost(GenTree** pTree, fgWalkData* fgWalkPost)
7863 {
7864     GenTree* tree   = *pTree;
7865     GenTree* parent = fgWalkPost->parent;
7866     if (parent != nullptr)
7867     {
7868         parent->gtFlags |= (tree->gtFlags & GTF_ALL_EFFECT);
7869     }
7870     return WALK_CONTINUE;
7871 }
7872
7873 /*****************************************************************************
7874  *
7875  *  Compares two trees and returns true when both trees are the same.
7876  *  Instead of fully comparing the two trees this method can just return false.
7877  *  Thus callers should not assume that the trees are different when false is returned.
7878  *  Only when true is returned can the caller perform code optimizations.
7879  *  The current implementation only compares a limited set of LEAF/CONST node
7880  *  and returns false for all othere trees.
7881  */
7882 bool Compiler::gtCompareTree(GenTree* op1, GenTree* op2)
7883 {
7884     /* Make sure that both trees are of the same GT node kind */
7885     if (op1->OperGet() != op2->OperGet())
7886     {
7887         return false;
7888     }
7889
7890     /* Make sure that both trees are returning the same type */
7891     if (op1->gtType != op2->gtType)
7892     {
7893         return false;
7894     }
7895
7896     /* Figure out what kind of a node we have */
7897
7898     genTreeOps oper = op1->OperGet();
7899     unsigned   kind = op1->OperKind();
7900
7901     /* Is this a constant or leaf node? */
7902
7903     if (kind & (GTK_CONST | GTK_LEAF))
7904     {
7905         switch (oper)
7906         {
7907             case GT_CNS_INT:
7908                 if ((op1->gtIntCon.gtIconVal == op2->gtIntCon.gtIconVal) && GenTree::SameIconHandleFlag(op1, op2))
7909                 {
7910                     return true;
7911                 }
7912                 break;
7913
7914             case GT_CNS_LNG:
7915                 if (op1->gtLngCon.gtLconVal == op2->gtLngCon.gtLconVal)
7916                 {
7917                     return true;
7918                 }
7919                 break;
7920
7921             case GT_CNS_STR:
7922                 if (op1->gtStrCon.gtSconCPX == op2->gtStrCon.gtSconCPX)
7923                 {
7924                     return true;
7925                 }
7926                 break;
7927
7928             case GT_LCL_VAR:
7929                 if (op1->gtLclVarCommon.gtLclNum == op2->gtLclVarCommon.gtLclNum)
7930                 {
7931                     return true;
7932                 }
7933                 break;
7934
7935             case GT_CLS_VAR:
7936                 if (op1->gtClsVar.gtClsVarHnd == op2->gtClsVar.gtClsVarHnd)
7937                 {
7938                     return true;
7939                 }
7940                 break;
7941
7942             default:
7943                 // we return false for these unhandled 'oper' kinds
7944                 break;
7945         }
7946     }
7947     return false;
7948 }
7949
7950 GenTree* Compiler::gtGetThisArg(GenTreeCall* call)
7951 {
7952     if (call->gtCallObjp != nullptr)
7953     {
7954         if (call->gtCallObjp->gtOper != GT_NOP && call->gtCallObjp->gtOper != GT_ASG)
7955         {
7956             if (!(call->gtCallObjp->gtFlags & GTF_LATE_ARG))
7957             {
7958                 return call->gtCallObjp;
7959             }
7960         }
7961
7962         if (call->gtCallLateArgs)
7963         {
7964             regNumber      thisReg         = REG_ARG_0;
7965             unsigned       argNum          = 0;
7966             fgArgTabEntry* thisArgTabEntry = gtArgEntryByArgNum(call, argNum);
7967             GenTree*       result          = thisArgTabEntry->node;
7968
7969 #if !FEATURE_FIXED_OUT_ARGS
7970             GenTree* lateArgs = call->gtCallLateArgs;
7971             regList  list     = call->regArgList;
7972             int      index    = 0;
7973             while (lateArgs != NULL)
7974             {
7975                 assert(lateArgs->gtOper == GT_LIST);
7976                 assert(index < call->regArgListCount);
7977                 regNumber curArgReg = list[index];
7978                 if (curArgReg == thisReg)
7979                 {
7980                     if (optAssertionPropagatedCurrentStmt)
7981                         result = lateArgs->gtOp.gtOp1;
7982
7983                     assert(result == lateArgs->gtOp.gtOp1);
7984                 }
7985
7986                 lateArgs = lateArgs->gtOp.gtOp2;
7987                 index++;
7988             }
7989 #endif
7990             return result;
7991         }
7992     }
7993     return nullptr;
7994 }
7995
7996 bool GenTree::gtSetFlags() const
7997 {
7998     //
7999     // When FEATURE_SET_FLAGS (_TARGET_ARM_) is active the method returns true
8000     //    when the gtFlags has the flag GTF_SET_FLAGS set
8001     // otherwise the architecture will be have instructions that typically set
8002     //    the flags and this method will return true.
8003     //
8004     //    Exceptions: GT_IND (load/store) is not allowed to set the flags
8005     //                and on XARCH the GT_MUL/GT_DIV and all overflow instructions
8006     //                do not set the condition flags
8007     //
8008     // Precondition we have a GTK_SMPOP
8009     //
8010     if (!varTypeIsIntegralOrI(TypeGet()) && (TypeGet() != TYP_VOID))
8011     {
8012         return false;
8013     }
8014
8015     if (((gtFlags & GTF_SET_FLAGS) != 0) && (gtOper != GT_IND))
8016     {
8017         // GTF_SET_FLAGS is not valid on GT_IND and is overlaid with GTF_NONFAULTING_IND
8018         return true;
8019     }
8020     else
8021     {
8022         return false;
8023     }
8024 }
8025
8026 bool GenTree::gtRequestSetFlags()
8027 {
8028     bool result = false;
8029
8030 #if FEATURE_SET_FLAGS
8031     // This method is a Nop unless FEATURE_SET_FLAGS is defined
8032
8033     // In order to set GTF_SET_FLAGS
8034     //              we must have a GTK_SMPOP
8035     //          and we have a integer or machine size type (not floating point or TYP_LONG on 32-bit)
8036     //
8037     if (!OperIsSimple())
8038         return false;
8039
8040     if (!varTypeIsIntegralOrI(TypeGet()))
8041         return false;
8042
8043     switch (gtOper)
8044     {
8045         case GT_IND:
8046         case GT_ARR_LENGTH:
8047             // These will turn into simple load from memory instructions
8048             // and we can't force the setting of the flags on load from memory
8049             break;
8050
8051         case GT_MUL:
8052         case GT_DIV:
8053             // These instructions don't set the flags (on x86/x64)
8054             //
8055             break;
8056
8057         default:
8058             // Otherwise we can set the flags for this gtOper
8059             // and codegen must set the condition flags.
8060             //
8061             gtFlags |= GTF_SET_FLAGS;
8062             result = true;
8063             break;
8064     }
8065 #endif // FEATURE_SET_FLAGS
8066
8067     // Codegen for this tree must set the condition flags if
8068     // this method returns true.
8069     //
8070     return result;
8071 }
8072
8073 unsigned GenTree::NumChildren()
8074 {
8075     if (OperIsConst() || OperIsLeaf())
8076     {
8077         return 0;
8078     }
8079     else if (OperIsUnary())
8080     {
8081         if (OperGet() == GT_NOP || OperGet() == GT_RETURN || OperGet() == GT_RETFILT)
8082         {
8083             if (gtOp.gtOp1 == nullptr)
8084             {
8085                 return 0;
8086             }
8087             else
8088             {
8089                 return 1;
8090             }
8091         }
8092         else
8093         {
8094             return 1;
8095         }
8096     }
8097     else if (OperIsBinary())
8098     {
8099         // All binary operators except LEA have at least one arg; the second arg may sometimes be null, however.
8100         if (OperGet() == GT_LEA)
8101         {
8102             unsigned childCount = 0;
8103             if (gtOp.gtOp1 != nullptr)
8104             {
8105                 childCount++;
8106             }
8107             if (gtOp.gtOp2 != nullptr)
8108             {
8109                 childCount++;
8110             }
8111             return childCount;
8112         }
8113 #ifdef FEATURE_HW_INTRINSICS
8114         // GT_HWIntrinsic require special handling
8115         if (OperGet() == GT_HWIntrinsic)
8116         {
8117             if (gtOp.gtOp1 == nullptr)
8118             {
8119                 return 0;
8120             }
8121         }
8122 #endif
8123         assert(gtOp.gtOp1 != nullptr);
8124         if (gtOp.gtOp2 == nullptr)
8125         {
8126             return 1;
8127         }
8128         else
8129         {
8130             return 2;
8131         }
8132     }
8133     else
8134     {
8135         // Special
8136         switch (OperGet())
8137         {
8138             case GT_CMPXCHG:
8139                 return 3;
8140
8141             case GT_ARR_BOUNDS_CHECK:
8142 #ifdef FEATURE_SIMD
8143             case GT_SIMD_CHK:
8144 #endif // FEATURE_SIMD
8145 #ifdef FEATURE_HW_INTRINSICS
8146             case GT_HW_INTRINSIC_CHK:
8147 #endif // FEATURE_HW_INTRINSICS
8148                 return 2;
8149
8150             case GT_FIELD:
8151             case GT_STMT:
8152                 return 1;
8153
8154             case GT_ARR_ELEM:
8155                 return 1 + AsArrElem()->gtArrRank;
8156
8157             case GT_DYN_BLK:
8158                 return 2;
8159
8160             case GT_ARR_OFFSET:
8161             case GT_STORE_DYN_BLK:
8162                 return 3;
8163
8164             case GT_CALL:
8165             {
8166                 GenTreeCall* call = AsCall();
8167                 unsigned     res  = 0; // arg list(s) (including late args).
8168                 if (call->gtCallObjp != nullptr)
8169                 {
8170                     res++; // Add objp?
8171                 }
8172                 if (call->gtCallArgs != nullptr)
8173                 {
8174                     res++; // Add args?
8175                 }
8176                 if (call->gtCallLateArgs != nullptr)
8177                 {
8178                     res++; // Add late args?
8179                 }
8180                 if (call->gtControlExpr != nullptr)
8181                 {
8182                     res++;
8183                 }
8184
8185                 if (call->gtCallType == CT_INDIRECT)
8186                 {
8187                     if (call->gtCallCookie != nullptr)
8188                     {
8189                         res++;
8190                     }
8191                     if (call->gtCallAddr != nullptr)
8192                     {
8193                         res++;
8194                     }
8195                 }
8196                 return res;
8197             }
8198             case GT_NONE:
8199                 return 0;
8200             default:
8201                 unreached();
8202         }
8203     }
8204 }
8205
8206 GenTree* GenTree::GetChild(unsigned childNum)
8207 {
8208     assert(childNum < NumChildren()); // Precondition.
8209     assert(NumChildren() <= MAX_CHILDREN);
8210     assert(!(OperIsConst() || OperIsLeaf()));
8211     if (OperIsUnary())
8212     {
8213         return AsUnOp()->gtOp1;
8214     }
8215     // Special case for assignment of dynamic block.
8216     // This code is here to duplicate the former case where the size may be evaluated prior to the
8217     // source and destination addresses. In order to do this, we treat the size as a child of the
8218     // assignment.
8219     // TODO-1stClassStructs: Revisit the need to duplicate former behavior, so that we can remove
8220     // these special cases.
8221     if ((OperGet() == GT_ASG) && (gtOp.gtOp1->OperGet() == GT_DYN_BLK) && (childNum == 2))
8222     {
8223         return gtOp.gtOp1->AsDynBlk()->gtDynamicSize;
8224     }
8225     else if (OperIsBinary())
8226     {
8227         if (OperIsAddrMode())
8228         {
8229             // If this is the first (0th) child, only return op1 if it is non-null
8230             // Otherwise, we return gtOp2.
8231             if (childNum == 0 && AsOp()->gtOp1 != nullptr)
8232             {
8233                 return AsOp()->gtOp1;
8234             }
8235             return AsOp()->gtOp2;
8236         }
8237         // TODO-Cleanup: Consider handling ReverseOps here, and then we wouldn't have to handle it in
8238         // fgGetFirstNode().  However, it seems that it causes loop hoisting behavior to change.
8239         if (childNum == 0)
8240         {
8241             return AsOp()->gtOp1;
8242         }
8243         else
8244         {
8245             return AsOp()->gtOp2;
8246         }
8247     }
8248     else
8249     {
8250         // Special
8251         switch (OperGet())
8252         {
8253             case GT_CMPXCHG:
8254                 switch (childNum)
8255                 {
8256                     case 0:
8257                         return AsCmpXchg()->gtOpLocation;
8258                     case 1:
8259                         return AsCmpXchg()->gtOpValue;
8260                     case 2:
8261                         return AsCmpXchg()->gtOpComparand;
8262                     default:
8263                         unreached();
8264                 }
8265             case GT_ARR_BOUNDS_CHECK:
8266 #ifdef FEATURE_SIMD
8267             case GT_SIMD_CHK:
8268 #endif // FEATURE_SIMD
8269 #ifdef FEATURE_HW_INTRINSICS
8270             case GT_HW_INTRINSIC_CHK:
8271 #endif // FEATURE_HW_INTRINSICS
8272                 switch (childNum)
8273                 {
8274                     case 0:
8275                         return AsBoundsChk()->gtIndex;
8276                     case 1:
8277                         return AsBoundsChk()->gtArrLen;
8278                     default:
8279                         unreached();
8280                 }
8281
8282             case GT_STORE_DYN_BLK:
8283                 switch (childNum)
8284                 {
8285                     case 0:
8286                         return AsDynBlk()->Addr();
8287                     case 1:
8288                         return AsDynBlk()->Data();
8289                     case 2:
8290                         return AsDynBlk()->gtDynamicSize;
8291                     default:
8292                         unreached();
8293                 }
8294             case GT_DYN_BLK:
8295                 switch (childNum)
8296                 {
8297                     case 0:
8298                         return AsDynBlk()->gtEvalSizeFirst ? AsDynBlk()->gtDynamicSize : AsDynBlk()->Addr();
8299                     case 1:
8300                         return AsDynBlk()->gtEvalSizeFirst ? AsDynBlk()->Addr() : AsDynBlk()->gtDynamicSize;
8301                     default:
8302                         unreached();
8303                 }
8304
8305             case GT_FIELD:
8306                 return AsField()->gtFldObj;
8307
8308             case GT_STMT:
8309                 return AsStmt()->gtStmtExpr;
8310
8311             case GT_ARR_ELEM:
8312                 if (childNum == 0)
8313                 {
8314                     return AsArrElem()->gtArrObj;
8315                 }
8316                 else
8317                 {
8318                     return AsArrElem()->gtArrInds[childNum - 1];
8319                 }
8320
8321             case GT_ARR_OFFSET:
8322                 switch (childNum)
8323                 {
8324                     case 0:
8325                         return AsArrOffs()->gtOffset;
8326                     case 1:
8327                         return AsArrOffs()->gtIndex;
8328                     case 2:
8329                         return AsArrOffs()->gtArrObj;
8330                     default:
8331                         unreached();
8332                 }
8333
8334             case GT_CALL:
8335             {
8336                 // The if chain below assumes that all possible children are non-null.
8337                 // If some are null, "virtually skip them."
8338                 // If there isn't "virtually skip it."
8339                 GenTreeCall* call = AsCall();
8340
8341                 if (call->gtCallObjp == nullptr)
8342                 {
8343                     childNum++;
8344                 }
8345                 if (childNum >= 1 && call->gtCallArgs == nullptr)
8346                 {
8347                     childNum++;
8348                 }
8349                 if (childNum >= 2 && call->gtCallLateArgs == nullptr)
8350                 {
8351                     childNum++;
8352                 }
8353                 if (childNum >= 3 && call->gtControlExpr == nullptr)
8354                 {
8355                     childNum++;
8356                 }
8357                 if (call->gtCallType == CT_INDIRECT)
8358                 {
8359                     if (childNum >= 4 && call->gtCallCookie == nullptr)
8360                     {
8361                         childNum++;
8362                     }
8363                 }
8364
8365                 if (childNum == 0)
8366                 {
8367                     return call->gtCallObjp;
8368                 }
8369                 else if (childNum == 1)
8370                 {
8371                     return call->gtCallArgs;
8372                 }
8373                 else if (childNum == 2)
8374                 {
8375                     return call->gtCallLateArgs;
8376                 }
8377                 else if (childNum == 3)
8378                 {
8379                     return call->gtControlExpr;
8380                 }
8381                 else
8382                 {
8383                     assert(call->gtCallType == CT_INDIRECT);
8384                     if (childNum == 4)
8385                     {
8386                         return call->gtCallCookie;
8387                     }
8388                     else
8389                     {
8390                         assert(childNum == 5);
8391                         return call->gtCallAddr;
8392                     }
8393                 }
8394             }
8395             case GT_NONE:
8396                 unreached();
8397             default:
8398                 unreached();
8399         }
8400     }
8401 }
8402
8403 GenTreeUseEdgeIterator::GenTreeUseEdgeIterator()
8404     : m_advance(nullptr), m_node(nullptr), m_edge(nullptr), m_argList(nullptr), m_state(-1)
8405 {
8406 }
8407
8408 GenTreeUseEdgeIterator::GenTreeUseEdgeIterator(GenTree* node)
8409     : m_advance(nullptr), m_node(node), m_edge(nullptr), m_argList(nullptr), m_state(0)
8410 {
8411     assert(m_node != nullptr);
8412
8413     // NOTE: the switch statement below must be updated when introducing new nodes.
8414
8415     switch (m_node->OperGet())
8416     {
8417         // Leaf nodes
8418         case GT_LCL_VAR:
8419         case GT_LCL_FLD:
8420         case GT_LCL_VAR_ADDR:
8421         case GT_LCL_FLD_ADDR:
8422         case GT_CATCH_ARG:
8423         case GT_LABEL:
8424         case GT_FTN_ADDR:
8425         case GT_RET_EXPR:
8426         case GT_CNS_INT:
8427         case GT_CNS_LNG:
8428         case GT_CNS_DBL:
8429         case GT_CNS_STR:
8430         case GT_MEMORYBARRIER:
8431         case GT_JMP:
8432         case GT_JCC:
8433         case GT_SETCC:
8434         case GT_NO_OP:
8435         case GT_START_NONGC:
8436         case GT_PROF_HOOK:
8437 #if !FEATURE_EH_FUNCLETS
8438         case GT_END_LFIN:
8439 #endif // !FEATURE_EH_FUNCLETS
8440         case GT_PHI_ARG:
8441         case GT_JMPTABLE:
8442         case GT_CLS_VAR:
8443         case GT_CLS_VAR_ADDR:
8444         case GT_ARGPLACE:
8445         case GT_PHYSREG:
8446         case GT_EMITNOP:
8447         case GT_PINVOKE_PROLOG:
8448         case GT_PINVOKE_EPILOG:
8449         case GT_IL_OFFSET:
8450             m_state = -1;
8451             return;
8452
8453         // Standard unary operators
8454         case GT_STORE_LCL_VAR:
8455         case GT_STORE_LCL_FLD:
8456         case GT_NOT:
8457         case GT_NEG:
8458         case GT_COPY:
8459         case GT_RELOAD:
8460         case GT_ARR_LENGTH:
8461         case GT_CAST:
8462         case GT_BITCAST:
8463         case GT_CKFINITE:
8464         case GT_LCLHEAP:
8465         case GT_ADDR:
8466         case GT_IND:
8467         case GT_OBJ:
8468         case GT_BLK:
8469         case GT_BOX:
8470         case GT_ALLOCOBJ:
8471         case GT_RUNTIMELOOKUP:
8472         case GT_INIT_VAL:
8473         case GT_JTRUE:
8474         case GT_SWITCH:
8475         case GT_NULLCHECK:
8476         case GT_PUTARG_REG:
8477         case GT_PUTARG_STK:
8478         case GT_BSWAP:
8479         case GT_BSWAP16:
8480 #if FEATURE_ARG_SPLIT
8481         case GT_PUTARG_SPLIT:
8482 #endif // FEATURE_ARG_SPLIT
8483         case GT_RETURNTRAP:
8484             m_edge = &m_node->AsUnOp()->gtOp1;
8485             assert(*m_edge != nullptr);
8486             m_advance = &GenTreeUseEdgeIterator::Terminate;
8487             return;
8488
8489         // Unary operators with an optional operand
8490         case GT_NOP:
8491         case GT_RETURN:
8492         case GT_RETFILT:
8493             if (m_node->AsUnOp()->gtOp1 == nullptr)
8494             {
8495                 assert(m_node->NullOp1Legal());
8496                 m_state = -1;
8497             }
8498             else
8499             {
8500                 m_edge    = &m_node->AsUnOp()->gtOp1;
8501                 m_advance = &GenTreeUseEdgeIterator::Terminate;
8502             }
8503             return;
8504
8505         // Variadic nodes
8506         case GT_PHI:
8507             SetEntryStateForList(m_node->AsUnOp()->gtOp1);
8508             return;
8509
8510         case GT_FIELD_LIST:
8511             SetEntryStateForList(m_node);
8512             return;
8513
8514 #ifdef FEATURE_SIMD
8515         case GT_SIMD:
8516             if (m_node->AsSIMD()->gtSIMDIntrinsicID == SIMDIntrinsicInitN)
8517             {
8518                 SetEntryStateForList(m_node->AsSIMD()->gtOp1);
8519             }
8520             else
8521             {
8522                 SetEntryStateForBinOp();
8523             }
8524             return;
8525 #endif // FEATURE_SIMD
8526
8527 #ifdef FEATURE_HW_INTRINSICS
8528         case GT_HWIntrinsic:
8529             if (m_node->AsHWIntrinsic()->gtOp1 == nullptr)
8530             {
8531                 assert(m_node->NullOp1Legal());
8532                 m_state = -1;
8533             }
8534             else if (m_node->AsHWIntrinsic()->gtOp1->OperIsList())
8535             {
8536                 SetEntryStateForList(m_node->AsHWIntrinsic()->gtOp1);
8537             }
8538             else
8539             {
8540                 SetEntryStateForBinOp();
8541             }
8542             return;
8543 #endif // FEATURE_HW_INTRINSICS
8544
8545         // LEA, which may have no first operand
8546         case GT_LEA:
8547             if (m_node->AsAddrMode()->gtOp1 == nullptr)
8548             {
8549                 m_edge    = &m_node->AsAddrMode()->gtOp2;
8550                 m_advance = &GenTreeUseEdgeIterator::Terminate;
8551             }
8552             else
8553             {
8554                 SetEntryStateForBinOp();
8555             }
8556             return;
8557
8558         // Special nodes
8559         case GT_CMPXCHG:
8560             m_edge = &m_node->AsCmpXchg()->gtOpLocation;
8561             assert(*m_edge != nullptr);
8562             m_advance = &GenTreeUseEdgeIterator::AdvanceCmpXchg;
8563             return;
8564
8565         case GT_ARR_BOUNDS_CHECK:
8566 #ifdef FEATURE_SIMD
8567         case GT_SIMD_CHK:
8568 #endif // FEATURE_SIMD
8569 #ifdef FEATURE_HW_INTRINSICS
8570         case GT_HW_INTRINSIC_CHK:
8571 #endif // FEATURE_HW_INTRINSICS
8572             m_edge = &m_node->AsBoundsChk()->gtIndex;
8573             assert(*m_edge != nullptr);
8574             m_advance = &GenTreeUseEdgeIterator::AdvanceBoundsChk;
8575             return;
8576
8577         case GT_FIELD:
8578             if (m_node->AsField()->gtFldObj == nullptr)
8579             {
8580                 m_state = -1;
8581             }
8582             else
8583             {
8584                 m_edge    = &m_node->AsField()->gtFldObj;
8585                 m_advance = &GenTreeUseEdgeIterator::Terminate;
8586             }
8587             return;
8588
8589         case GT_STMT:
8590             if (m_node->AsStmt()->gtStmtExpr == nullptr)
8591             {
8592                 m_state = -1;
8593             }
8594             else
8595             {
8596                 m_edge    = &m_node->AsStmt()->gtStmtExpr;
8597                 m_advance = &GenTreeUseEdgeIterator::Terminate;
8598             }
8599             return;
8600
8601         case GT_ARR_ELEM:
8602             m_edge = &m_node->AsArrElem()->gtArrObj;
8603             assert(*m_edge != nullptr);
8604             m_advance = &GenTreeUseEdgeIterator::AdvanceArrElem;
8605             return;
8606
8607         case GT_ARR_OFFSET:
8608             m_edge = &m_node->AsArrOffs()->gtOffset;
8609             assert(*m_edge != nullptr);
8610             m_advance = &GenTreeUseEdgeIterator::AdvanceArrOffset;
8611             return;
8612
8613         case GT_DYN_BLK:
8614         {
8615             GenTreeDynBlk* const dynBlock = m_node->AsDynBlk();
8616             m_edge                        = dynBlock->gtEvalSizeFirst ? &dynBlock->gtDynamicSize : &dynBlock->gtOp1;
8617             assert(*m_edge != nullptr);
8618             m_advance = &GenTreeUseEdgeIterator::AdvanceDynBlk;
8619         }
8620             return;
8621
8622         case GT_STORE_DYN_BLK:
8623         {
8624             GenTreeDynBlk* const dynBlock = m_node->AsDynBlk();
8625             if (dynBlock->gtEvalSizeFirst)
8626             {
8627                 m_edge = &dynBlock->gtDynamicSize;
8628             }
8629             else
8630             {
8631                 m_edge = dynBlock->IsReverseOp() ? &dynBlock->gtOp2 : &dynBlock->gtOp1;
8632             }
8633             assert(*m_edge != nullptr);
8634
8635             m_advance = &GenTreeUseEdgeIterator::AdvanceStoreDynBlk;
8636         }
8637             return;
8638
8639         case GT_CALL:
8640             AdvanceCall<CALL_INSTANCE>();
8641             return;
8642
8643         // Binary nodes
8644         default:
8645             assert(m_node->OperIsBinary());
8646             SetEntryStateForBinOp();
8647             return;
8648     }
8649 }
8650
8651 //------------------------------------------------------------------------
8652 // GenTreeUseEdgeIterator::AdvanceCmpXchg: produces the next operand of a CmpXchg node and advances the state.
8653 //
8654 void GenTreeUseEdgeIterator::AdvanceCmpXchg()
8655 {
8656     switch (m_state)
8657     {
8658         case 0:
8659             m_edge  = &m_node->AsCmpXchg()->gtOpValue;
8660             m_state = 1;
8661             break;
8662         case 1:
8663             m_edge    = &m_node->AsCmpXchg()->gtOpComparand;
8664             m_advance = &GenTreeUseEdgeIterator::Terminate;
8665             break;
8666         default:
8667             unreached();
8668     }
8669
8670     assert(*m_edge != nullptr);
8671 }
8672
8673 //------------------------------------------------------------------------
8674 // GenTreeUseEdgeIterator::AdvanceBoundsChk: produces the next operand of a BoundsChk node and advances the state.
8675 //
8676 void GenTreeUseEdgeIterator::AdvanceBoundsChk()
8677 {
8678     m_edge = &m_node->AsBoundsChk()->gtArrLen;
8679     assert(*m_edge != nullptr);
8680     m_advance = &GenTreeUseEdgeIterator::Terminate;
8681 }
8682
8683 //------------------------------------------------------------------------
8684 // GenTreeUseEdgeIterator::AdvanceArrElem: produces the next operand of a ArrElem node and advances the state.
8685 //
8686 // Because these nodes are variadic, this function uses `m_state` to index into the list of array indices.
8687 //
8688 void GenTreeUseEdgeIterator::AdvanceArrElem()
8689 {
8690     if (m_state < m_node->AsArrElem()->gtArrRank)
8691     {
8692         m_edge = &m_node->AsArrElem()->gtArrInds[m_state];
8693         assert(*m_edge != nullptr);
8694         m_state++;
8695     }
8696     else
8697     {
8698         m_state = -1;
8699     }
8700 }
8701
8702 //------------------------------------------------------------------------
8703 // GenTreeUseEdgeIterator::AdvanceArrOffset: produces the next operand of a ArrOffset node and advances the state.
8704 //
8705 void GenTreeUseEdgeIterator::AdvanceArrOffset()
8706 {
8707     switch (m_state)
8708     {
8709         case 0:
8710             m_edge  = &m_node->AsArrOffs()->gtIndex;
8711             m_state = 1;
8712             break;
8713         case 1:
8714             m_edge    = &m_node->AsArrOffs()->gtArrObj;
8715             m_advance = &GenTreeUseEdgeIterator::Terminate;
8716             break;
8717         default:
8718             unreached();
8719     }
8720
8721     assert(*m_edge != nullptr);
8722 }
8723
8724 //------------------------------------------------------------------------
8725 // GenTreeUseEdgeIterator::AdvanceDynBlk: produces the next operand of a DynBlk node and advances the state.
8726 //
8727 void GenTreeUseEdgeIterator::AdvanceDynBlk()
8728 {
8729     GenTreeDynBlk* const dynBlock = m_node->AsDynBlk();
8730
8731     m_edge = dynBlock->gtEvalSizeFirst ? &dynBlock->gtOp1 : &dynBlock->gtDynamicSize;
8732     assert(*m_edge != nullptr);
8733     m_advance = &GenTreeUseEdgeIterator::Terminate;
8734 }
8735
8736 //------------------------------------------------------------------------
8737 // GenTreeUseEdgeIterator::AdvanceStoreDynBlk: produces the next operand of a StoreDynBlk node and advances the state.
8738 //
8739 // These nodes are moderately complicated but rare enough that templating this function is probably not
8740 // worth the extra complexity.
8741 //
8742 void GenTreeUseEdgeIterator::AdvanceStoreDynBlk()
8743 {
8744     GenTreeDynBlk* const dynBlock = m_node->AsDynBlk();
8745     if (dynBlock->gtEvalSizeFirst)
8746     {
8747         switch (m_state)
8748         {
8749             case 0:
8750                 m_edge  = dynBlock->IsReverseOp() ? &dynBlock->gtOp2 : &dynBlock->gtOp1;
8751                 m_state = 1;
8752                 break;
8753             case 1:
8754                 m_edge    = dynBlock->IsReverseOp() ? &dynBlock->gtOp1 : &dynBlock->gtOp2;
8755                 m_advance = &GenTreeUseEdgeIterator::Terminate;
8756                 break;
8757             default:
8758                 unreached();
8759         }
8760     }
8761     else
8762     {
8763         switch (m_state)
8764         {
8765             case 0:
8766                 m_edge  = dynBlock->IsReverseOp() ? &dynBlock->gtOp1 : &dynBlock->gtOp2;
8767                 m_state = 1;
8768                 break;
8769             case 1:
8770                 m_edge    = &dynBlock->gtDynamicSize;
8771                 m_advance = &GenTreeUseEdgeIterator::Terminate;
8772                 break;
8773             default:
8774                 unreached();
8775         }
8776     }
8777
8778     assert(*m_edge != nullptr);
8779 }
8780
8781 //------------------------------------------------------------------------
8782 // GenTreeUseEdgeIterator::AdvanceBinOp: produces the next operand of a binary node and advances the state.
8783 //
8784 // This function must be instantiated s.t. `ReverseOperands` is `true` iff the node is marked with the
8785 // `GTF_REVERSE_OPS` flag.
8786 //
8787 template <bool ReverseOperands>
8788 void           GenTreeUseEdgeIterator::AdvanceBinOp()
8789 {
8790     assert(ReverseOperands == ((m_node->gtFlags & GTF_REVERSE_OPS) != 0));
8791
8792     m_edge = !ReverseOperands ? &m_node->AsOp()->gtOp2 : &m_node->AsOp()->gtOp1;
8793     assert(*m_edge != nullptr);
8794     m_advance = &GenTreeUseEdgeIterator::Terminate;
8795 }
8796
8797 //------------------------------------------------------------------------
8798 // GenTreeUseEdgeIterator::SetEntryStateForBinOp: produces the first operand of a binary node and chooses
8799 //                                                the appropriate advance function.
8800 //
8801 void GenTreeUseEdgeIterator::SetEntryStateForBinOp()
8802 {
8803     assert(m_node != nullptr);
8804     assert(m_node->OperIsBinary());
8805
8806     GenTreeOp* const node = m_node->AsOp();
8807
8808     if (node->gtOp2 == nullptr)
8809     {
8810         assert(node->gtOp1 != nullptr);
8811         assert(node->NullOp2Legal());
8812         m_edge    = &node->gtOp1;
8813         m_advance = &GenTreeUseEdgeIterator::Terminate;
8814     }
8815     else if ((node->gtFlags & GTF_REVERSE_OPS) != 0)
8816     {
8817         m_edge    = &m_node->AsOp()->gtOp2;
8818         m_advance = &GenTreeUseEdgeIterator::AdvanceBinOp<true>;
8819     }
8820     else
8821     {
8822         m_edge    = &m_node->AsOp()->gtOp1;
8823         m_advance = &GenTreeUseEdgeIterator::AdvanceBinOp<false>;
8824     }
8825 }
8826
8827 //------------------------------------------------------------------------
8828 // GenTreeUseEdgeIterator::AdvanceList: produces the next operand of a variadic node and advances the state.
8829 //
8830 // This function does not use `m_state` for anything meaningful; it simply walks the `m_argList` until
8831 // there are no further entries.
8832 //
8833 void GenTreeUseEdgeIterator::AdvanceList()
8834 {
8835     assert(m_state == 0);
8836
8837     if (m_argList == nullptr)
8838     {
8839         m_state = -1;
8840     }
8841     else
8842     {
8843         GenTreeArgList* listNode = m_argList->AsArgList();
8844         m_edge                   = &listNode->gtOp1;
8845         m_argList                = listNode->Rest();
8846     }
8847 }
8848
8849 //------------------------------------------------------------------------
8850 // GenTreeUseEdgeIterator::SetEntryStateForList: produces the first operand of a list node.
8851 //
8852 void GenTreeUseEdgeIterator::SetEntryStateForList(GenTree* list)
8853 {
8854     m_argList = list;
8855     m_advance = &GenTreeUseEdgeIterator::AdvanceList;
8856     AdvanceList();
8857 }
8858
8859 //------------------------------------------------------------------------
8860 // GenTreeUseEdgeIterator::AdvanceCall: produces the next operand of a call node and advances the state.
8861 //
8862 // This function is a bit tricky: in order to avoid doing unnecessary work, it is instantiated with the
8863 // state number the iterator will be in when it is called. For example, `AdvanceCall<CALL_INSTANCE>`
8864 // is the instantiation used when the iterator is at the `CALL_INSTANCE` state (i.e. the entry state).
8865 // This sort of templating allows each state to avoid processing earlier states without unnecessary
8866 // duplication of code.
8867 //
8868 // Note that this method expands the argument lists (`gtCallArgs` and `gtCallLateArgs`) into their
8869 // component operands.
8870 //
8871 template <int state>
8872 void          GenTreeUseEdgeIterator::AdvanceCall()
8873 {
8874     GenTreeCall* const call = m_node->AsCall();
8875
8876     switch (state)
8877     {
8878         case CALL_INSTANCE:
8879             m_argList = call->gtCallArgs;
8880             m_advance = &GenTreeUseEdgeIterator::AdvanceCall<CALL_ARGS>;
8881             if (call->gtCallObjp != nullptr)
8882             {
8883                 m_edge = &call->gtCallObjp;
8884                 return;
8885             }
8886             __fallthrough;
8887
8888         case CALL_ARGS:
8889             if (m_argList != nullptr)
8890             {
8891                 GenTreeArgList* argNode = m_argList->AsArgList();
8892                 m_edge                  = &argNode->gtOp1;
8893                 m_argList               = argNode->Rest();
8894                 return;
8895             }
8896             m_argList = call->gtCallLateArgs;
8897             m_advance = &GenTreeUseEdgeIterator::AdvanceCall<CALL_LATE_ARGS>;
8898             __fallthrough;
8899
8900         case CALL_LATE_ARGS:
8901             if (m_argList != nullptr)
8902             {
8903                 GenTreeArgList* argNode = m_argList->AsArgList();
8904                 m_edge                  = &argNode->gtOp1;
8905                 m_argList               = argNode->Rest();
8906                 return;
8907             }
8908             m_advance = &GenTreeUseEdgeIterator::AdvanceCall<CALL_CONTROL_EXPR>;
8909             __fallthrough;
8910
8911         case CALL_CONTROL_EXPR:
8912             if (call->gtControlExpr != nullptr)
8913             {
8914                 if (call->gtCallType == CT_INDIRECT)
8915                 {
8916                     m_advance = &GenTreeUseEdgeIterator::AdvanceCall<CALL_COOKIE>;
8917                 }
8918                 else
8919                 {
8920                     m_advance = &GenTreeUseEdgeIterator::Terminate;
8921                 }
8922                 m_edge = &call->gtControlExpr;
8923                 return;
8924             }
8925             else if (call->gtCallType != CT_INDIRECT)
8926             {
8927                 m_state = -1;
8928                 return;
8929             }
8930             __fallthrough;
8931
8932         case CALL_COOKIE:
8933             assert(call->gtCallType == CT_INDIRECT);
8934
8935             m_advance = &GenTreeUseEdgeIterator::AdvanceCall<CALL_ADDRESS>;
8936             if (call->gtCallCookie != nullptr)
8937             {
8938                 m_edge = &call->gtCallCookie;
8939                 return;
8940             }
8941             __fallthrough;
8942
8943         case CALL_ADDRESS:
8944             assert(call->gtCallType == CT_INDIRECT);
8945
8946             m_advance = &GenTreeUseEdgeIterator::Terminate;
8947             if (call->gtCallAddr != nullptr)
8948             {
8949                 m_edge = &call->gtCallAddr;
8950             }
8951             return;
8952
8953         default:
8954             unreached();
8955     }
8956 }
8957
8958 //------------------------------------------------------------------------
8959 // GenTreeUseEdgeIterator::Terminate: advances the iterator to the terminal state.
8960 //
8961 void GenTreeUseEdgeIterator::Terminate()
8962 {
8963     m_state = -1;
8964 }
8965
8966 //------------------------------------------------------------------------
8967 // GenTreeUseEdgeIterator::operator++: advances the iterator to the next operand.
8968 //
8969 GenTreeUseEdgeIterator& GenTreeUseEdgeIterator::operator++()
8970 {
8971     // If we've reached the terminal state, do nothing.
8972     if (m_state != -1)
8973     {
8974         (this->*m_advance)();
8975     }
8976
8977     return *this;
8978 }
8979
8980 GenTreeUseEdgeIterator GenTree::UseEdgesBegin()
8981 {
8982     return GenTreeUseEdgeIterator(this);
8983 }
8984
8985 GenTreeUseEdgeIterator GenTree::UseEdgesEnd()
8986 {
8987     return GenTreeUseEdgeIterator();
8988 }
8989
8990 IteratorPair<GenTreeUseEdgeIterator> GenTree::UseEdges()
8991 {
8992     return MakeIteratorPair(UseEdgesBegin(), UseEdgesEnd());
8993 }
8994
8995 GenTreeOperandIterator GenTree::OperandsBegin()
8996 {
8997     return GenTreeOperandIterator(this);
8998 }
8999
9000 GenTreeOperandIterator GenTree::OperandsEnd()
9001 {
9002     return GenTreeOperandIterator();
9003 }
9004
9005 IteratorPair<GenTreeOperandIterator> GenTree::Operands()
9006 {
9007     return MakeIteratorPair(OperandsBegin(), OperandsEnd());
9008 }
9009
9010 bool GenTree::Precedes(GenTree* other)
9011 {
9012     assert(other != nullptr);
9013
9014     for (GenTree* node = gtNext; node != nullptr; node = node->gtNext)
9015     {
9016         if (node == other)
9017         {
9018             return true;
9019         }
9020     }
9021
9022     return false;
9023 }
9024
9025 #ifdef DEBUG
9026
9027 /* static */ int GenTree::gtDispFlags(unsigned flags, unsigned debugFlags)
9028 {
9029     int charsDisplayed = 11; // 11 is the "baseline" number of flag characters displayed
9030
9031     printf("%c", (flags & GTF_ASG) ? 'A' : (IsContained(flags) ? 'c' : '-'));
9032     printf("%c", (flags & GTF_CALL) ? 'C' : '-');
9033     printf("%c", (flags & GTF_EXCEPT) ? 'X' : '-');
9034     printf("%c", (flags & GTF_GLOB_REF) ? 'G' : '-');
9035     printf("%c", (debugFlags & GTF_DEBUG_NODE_MORPHED) ? '+' : // First print '+' if GTF_DEBUG_NODE_MORPHED is set
9036                      (flags & GTF_ORDER_SIDEEFF) ? 'O' : '-'); // otherwise print 'O' or '-'
9037     printf("%c", (flags & GTF_COLON_COND) ? '?' : '-');
9038     printf("%c", (flags & GTF_DONT_CSE) ? 'N' :           // N is for No cse
9039                      (flags & GTF_MAKE_CSE) ? 'H' : '-'); // H is for Hoist this expr
9040     printf("%c", (flags & GTF_REVERSE_OPS) ? 'R' : '-');
9041     printf("%c", (flags & GTF_UNSIGNED) ? 'U' : (flags & GTF_BOOLEAN) ? 'B' : '-');
9042 #if FEATURE_SET_FLAGS
9043     printf("%c", (flags & GTF_SET_FLAGS) ? 'S' : '-');
9044     ++charsDisplayed;
9045 #endif
9046     printf("%c", (flags & GTF_LATE_ARG) ? 'L' : '-');
9047     printf("%c", (flags & GTF_SPILLED) ? 'z' : (flags & GTF_SPILL) ? 'Z' : '-');
9048
9049     return charsDisplayed;
9050 }
9051
9052 /*****************************************************************************/
9053
9054 void Compiler::gtDispNodeName(GenTree* tree)
9055 {
9056     /* print the node name */
9057
9058     const char* name;
9059
9060     assert(tree);
9061     if (tree->gtOper < GT_COUNT)
9062     {
9063         name = GenTree::OpName(tree->OperGet());
9064     }
9065     else
9066     {
9067         name = "<ERROR>";
9068     }
9069     char  buf[32];
9070     char* bufp = &buf[0];
9071
9072     if ((tree->gtOper == GT_CNS_INT) && tree->IsIconHandle())
9073     {
9074         sprintf_s(bufp, sizeof(buf), " %s(h)%c", name, 0);
9075     }
9076     else if (tree->gtOper == GT_PUTARG_STK)
9077     {
9078         sprintf_s(bufp, sizeof(buf), " %s [+0x%02x]%c", name, tree->AsPutArgStk()->getArgOffset(), 0);
9079     }
9080     else if (tree->gtOper == GT_CALL)
9081     {
9082         const char* callType = "CALL";
9083         const char* gtfType  = "";
9084         const char* ctType   = "";
9085         char        gtfTypeBuf[100];
9086
9087         if (tree->gtCall.gtCallType == CT_USER_FUNC)
9088         {
9089             if (tree->gtCall.IsVirtual())
9090             {
9091                 callType = "CALLV";
9092             }
9093         }
9094         else if (tree->gtCall.gtCallType == CT_HELPER)
9095         {
9096             ctType = " help";
9097         }
9098         else if (tree->gtCall.gtCallType == CT_INDIRECT)
9099         {
9100             ctType = " ind";
9101         }
9102         else
9103         {
9104             assert(!"Unknown gtCallType");
9105         }
9106
9107         if (tree->gtFlags & GTF_CALL_NULLCHECK)
9108         {
9109             gtfType = " nullcheck";
9110         }
9111         if (tree->gtCall.IsVirtualVtable())
9112         {
9113             gtfType = " ind";
9114         }
9115         else if (tree->gtCall.IsVirtualStub())
9116         {
9117             gtfType = " stub";
9118         }
9119 #ifdef FEATURE_READYTORUN_COMPILER
9120         else if (tree->gtCall.IsR2RRelativeIndir())
9121         {
9122             gtfType = " r2r_ind";
9123         }
9124 #endif // FEATURE_READYTORUN_COMPILER
9125         else if (tree->gtFlags & GTF_CALL_UNMANAGED)
9126         {
9127             char* gtfTypeBufWalk = gtfTypeBuf;
9128             gtfTypeBufWalk += SimpleSprintf_s(gtfTypeBufWalk, gtfTypeBuf, sizeof(gtfTypeBuf), " unman");
9129             if (tree->gtFlags & GTF_CALL_POP_ARGS)
9130             {
9131                 gtfTypeBufWalk += SimpleSprintf_s(gtfTypeBufWalk, gtfTypeBuf, sizeof(gtfTypeBuf), " popargs");
9132             }
9133             if (tree->gtCall.gtCallMoreFlags & GTF_CALL_M_UNMGD_THISCALL)
9134             {
9135                 gtfTypeBufWalk += SimpleSprintf_s(gtfTypeBufWalk, gtfTypeBuf, sizeof(gtfTypeBuf), " thiscall");
9136             }
9137             gtfType = gtfTypeBuf;
9138         }
9139
9140         sprintf_s(bufp, sizeof(buf), " %s%s%s%c", callType, ctType, gtfType, 0);
9141     }
9142     else if (tree->gtOper == GT_ARR_ELEM)
9143     {
9144         bufp += SimpleSprintf_s(bufp, buf, sizeof(buf), " %s[", name);
9145         for (unsigned rank = tree->gtArrElem.gtArrRank - 1; rank; rank--)
9146         {
9147             bufp += SimpleSprintf_s(bufp, buf, sizeof(buf), ",");
9148         }
9149         SimpleSprintf_s(bufp, buf, sizeof(buf), "]");
9150     }
9151     else if (tree->gtOper == GT_ARR_OFFSET || tree->gtOper == GT_ARR_INDEX)
9152     {
9153         bufp += SimpleSprintf_s(bufp, buf, sizeof(buf), " %s[", name);
9154         unsigned char currDim;
9155         unsigned char rank;
9156         if (tree->gtOper == GT_ARR_OFFSET)
9157         {
9158             currDim = tree->gtArrOffs.gtCurrDim;
9159             rank    = tree->gtArrOffs.gtArrRank;
9160         }
9161         else
9162         {
9163             currDim = tree->gtArrIndex.gtCurrDim;
9164             rank    = tree->gtArrIndex.gtArrRank;
9165         }
9166
9167         for (unsigned char dim = 0; dim < rank; dim++)
9168         {
9169             // Use a defacto standard i,j,k for the dimensions.
9170             // Note that we only support up to rank 3 arrays with these nodes, so we won't run out of characters.
9171             char dimChar = '*';
9172             if (dim == currDim)
9173             {
9174                 dimChar = 'i' + dim;
9175             }
9176             else if (dim > currDim)
9177             {
9178                 dimChar = ' ';
9179             }
9180
9181             bufp += SimpleSprintf_s(bufp, buf, sizeof(buf), "%c", dimChar);
9182             if (dim != rank - 1)
9183             {
9184                 bufp += SimpleSprintf_s(bufp, buf, sizeof(buf), ",");
9185             }
9186         }
9187         SimpleSprintf_s(bufp, buf, sizeof(buf), "]");
9188     }
9189     else if (tree->gtOper == GT_LEA)
9190     {
9191         GenTreeAddrMode* lea = tree->AsAddrMode();
9192         bufp += SimpleSprintf_s(bufp, buf, sizeof(buf), " %s(", name);
9193         if (lea->Base() != nullptr)
9194         {
9195             bufp += SimpleSprintf_s(bufp, buf, sizeof(buf), "b+");
9196         }
9197         if (lea->Index() != nullptr)
9198         {
9199             bufp += SimpleSprintf_s(bufp, buf, sizeof(buf), "(i*%d)+", lea->gtScale);
9200         }
9201         bufp += SimpleSprintf_s(bufp, buf, sizeof(buf), "%d)", lea->Offset());
9202     }
9203     else if (tree->gtOper == GT_ARR_BOUNDS_CHECK)
9204     {
9205         switch (tree->gtBoundsChk.gtThrowKind)
9206         {
9207             case SCK_RNGCHK_FAIL:
9208                 sprintf_s(bufp, sizeof(buf), " %s_Rng", name);
9209                 break;
9210             case SCK_ARG_EXCPN:
9211                 sprintf_s(bufp, sizeof(buf), " %s_Arg", name);
9212                 break;
9213             case SCK_ARG_RNG_EXCPN:
9214                 sprintf_s(bufp, sizeof(buf), " %s_ArgRng", name);
9215                 break;
9216             default:
9217                 unreached();
9218         }
9219     }
9220     else if (tree->gtOverflowEx())
9221     {
9222         sprintf_s(bufp, sizeof(buf), " %s_ovfl%c", name, 0);
9223     }
9224     else if (tree->OperIsBlk() && !tree->OperIsDynBlk())
9225     {
9226         sprintf_s(bufp, sizeof(buf), " %s(%d)", name, tree->AsBlk()->gtBlkSize);
9227     }
9228     else
9229     {
9230         sprintf_s(bufp, sizeof(buf), " %s%c", name, 0);
9231     }
9232
9233     if (strlen(buf) < 10)
9234     {
9235         printf(" %-10s", buf);
9236     }
9237     else
9238     {
9239         printf(" %s", buf);
9240     }
9241 }
9242
9243 void Compiler::gtDispVN(GenTree* tree)
9244 {
9245     if (tree->gtVNPair.GetLiberal() != ValueNumStore::NoVN)
9246     {
9247         assert(tree->gtVNPair.GetConservative() != ValueNumStore::NoVN);
9248         printf(" ");
9249         vnpPrint(tree->gtVNPair, 0);
9250     }
9251 }
9252
9253 //------------------------------------------------------------------------
9254 // gtDispNode: Print a tree to jitstdout.
9255 //
9256 // Arguments:
9257 //    tree - the tree to be printed
9258 //    indentStack - the specification for the current level of indentation & arcs
9259 //    msg         - a contextual method (i.e. from the parent) to print
9260 //
9261 // Return Value:
9262 //    None.
9263 //
9264 // Notes:
9265 //    'indentStack' may be null, in which case no indentation or arcs are printed
9266 //    'msg' may be null
9267
9268 void Compiler::gtDispNode(GenTree* tree, IndentStack* indentStack, __in __in_z __in_opt const char* msg, bool isLIR)
9269 {
9270     bool printPointer = true; // always true..
9271     bool printFlags   = true; // always true..
9272     bool printCost    = true; // always true..
9273
9274     int msgLength = 25;
9275
9276     GenTree* prev;
9277
9278     if (tree->gtSeqNum)
9279     {
9280         printf("N%03u ", tree->gtSeqNum);
9281         if (tree->gtCostsInitialized)
9282         {
9283             printf("(%3u,%3u) ", tree->gtCostEx, tree->gtCostSz);
9284         }
9285         else
9286         {
9287             printf("(???"
9288                    ",???"
9289                    ") "); // This probably indicates a bug: the node has a sequence number, but not costs.
9290         }
9291     }
9292     else
9293     {
9294         if (tree->gtOper == GT_STMT)
9295         {
9296             prev = tree->gtStmt.gtStmtExpr;
9297         }
9298         else
9299         {
9300             prev = tree;
9301         }
9302
9303         bool     hasSeqNum = true;
9304         unsigned dotNum    = 0;
9305         do
9306         {
9307             dotNum++;
9308             prev = prev->gtPrev;
9309
9310             if ((prev == nullptr) || (prev == tree))
9311             {
9312                 hasSeqNum = false;
9313                 break;
9314             }
9315
9316             assert(prev);
9317         } while (prev->gtSeqNum == 0);
9318
9319         // If we have an indent stack, don't add additional characters,
9320         // as it will mess up the alignment.
9321         bool displayDotNum = tree->gtOper != GT_STMT && hasSeqNum && (indentStack == nullptr);
9322         if (displayDotNum)
9323         {
9324             printf("N%03u.%02u ", prev->gtSeqNum, dotNum);
9325         }
9326         else
9327         {
9328             printf("     ");
9329         }
9330
9331         if (tree->gtCostsInitialized)
9332         {
9333             printf("(%3u,%3u) ", tree->gtCostEx, tree->gtCostSz);
9334         }
9335         else
9336         {
9337             if (displayDotNum)
9338             {
9339                 // Do better alignment in this case
9340                 printf("       ");
9341             }
9342             else
9343             {
9344                 printf("          ");
9345             }
9346         }
9347     }
9348
9349     if (optValnumCSE_phase)
9350     {
9351         if (IS_CSE_INDEX(tree->gtCSEnum))
9352         {
9353             printf("CSE #%02d (%s)", GET_CSE_INDEX(tree->gtCSEnum), (IS_CSE_USE(tree->gtCSEnum) ? "use" : "def"));
9354         }
9355         else
9356         {
9357             printf("             ");
9358         }
9359     }
9360
9361     /* Print the node ID */
9362     printTreeID(tree);
9363     printf(" ");
9364
9365     if (tree->gtOper >= GT_COUNT)
9366     {
9367         printf(" **** ILLEGAL NODE ****");
9368         return;
9369     }
9370
9371     if (printFlags)
9372     {
9373         /* First print the flags associated with the node */
9374         switch (tree->gtOper)
9375         {
9376             case GT_LEA:
9377             case GT_BLK:
9378             case GT_OBJ:
9379             case GT_DYN_BLK:
9380             case GT_STORE_BLK:
9381             case GT_STORE_OBJ:
9382             case GT_STORE_DYN_BLK:
9383
9384             case GT_IND:
9385                 // We prefer printing V or U
9386                 if ((tree->gtFlags & (GTF_IND_VOLATILE | GTF_IND_UNALIGNED)) == 0)
9387                 {
9388                     if (tree->gtFlags & GTF_IND_TGTANYWHERE)
9389                     {
9390                         printf("*");
9391                         --msgLength;
9392                         break;
9393                     }
9394                     if (tree->gtFlags & GTF_IND_INVARIANT)
9395                     {
9396                         printf("#");
9397                         --msgLength;
9398                         break;
9399                     }
9400                     if (tree->gtFlags & GTF_IND_ARR_INDEX)
9401                     {
9402                         printf("a");
9403                         --msgLength;
9404                         break;
9405                     }
9406                     if (tree->gtFlags & GTF_IND_NONFAULTING)
9407                     {
9408                         printf("n"); // print a n for non-faulting
9409                         --msgLength;
9410                         break;
9411                     }
9412                     if (tree->gtFlags & GTF_IND_ASG_LHS)
9413                     {
9414                         printf("D"); // print a D for definition
9415                         --msgLength;
9416                         break;
9417                     }
9418                 }
9419                 __fallthrough;
9420
9421             case GT_INDEX:
9422             case GT_INDEX_ADDR:
9423
9424                 if ((tree->gtFlags & (GTF_IND_VOLATILE | GTF_IND_UNALIGNED)) == 0) // We prefer printing V or U over R
9425                 {
9426                     if (tree->gtFlags & GTF_INX_REFARR_LAYOUT)
9427                     {
9428                         printf("R");
9429                         --msgLength;
9430                         break;
9431                     } // R means RefArray
9432                 }
9433                 __fallthrough;
9434
9435             case GT_FIELD:
9436             case GT_CLS_VAR:
9437                 if (tree->gtFlags & GTF_IND_VOLATILE)
9438                 {
9439                     printf("V");
9440                     --msgLength;
9441                     break;
9442                 }
9443                 if (tree->gtFlags & GTF_IND_UNALIGNED)
9444                 {
9445                     printf("U");
9446                     --msgLength;
9447                     break;
9448                 }
9449                 goto DASH;
9450
9451             case GT_ASG:
9452                 if (tree->OperIsInitBlkOp())
9453                 {
9454                     printf("I");
9455                     --msgLength;
9456                     break;
9457                 }
9458                 goto DASH;
9459
9460             case GT_CALL:
9461                 if (tree->gtCall.IsInlineCandidate())
9462                 {
9463                     if (tree->gtCall.IsGuardedDevirtualizationCandidate())
9464                     {
9465                         printf("&");
9466                     }
9467                     else
9468                     {
9469                         printf("I");
9470                     }
9471                     --msgLength;
9472                     break;
9473                 }
9474                 else if (tree->gtCall.IsGuardedDevirtualizationCandidate())
9475                 {
9476                     printf("G");
9477                     --msgLength;
9478                     break;
9479                 }
9480                 if (tree->gtCall.gtCallMoreFlags & GTF_CALL_M_RETBUFFARG)
9481                 {
9482                     printf("S");
9483                     --msgLength;
9484                     break;
9485                 }
9486                 if (tree->gtFlags & GTF_CALL_HOISTABLE)
9487                 {
9488                     printf("H");
9489                     --msgLength;
9490                     break;
9491                 }
9492
9493                 goto DASH;
9494
9495             case GT_MUL:
9496 #if !defined(_TARGET_64BIT_)
9497             case GT_MUL_LONG:
9498 #endif
9499                 if (tree->gtFlags & GTF_MUL_64RSLT)
9500                 {
9501                     printf("L");
9502                     --msgLength;
9503                     break;
9504                 }
9505                 goto DASH;
9506
9507             case GT_ADDR:
9508                 if (tree->gtFlags & GTF_ADDR_ONSTACK)
9509                 {
9510                     printf("L");
9511                     --msgLength;
9512                     break;
9513                 } // L means LclVar
9514                 goto DASH;
9515
9516             case GT_LCL_FLD:
9517             case GT_LCL_VAR:
9518             case GT_LCL_VAR_ADDR:
9519             case GT_LCL_FLD_ADDR:
9520             case GT_STORE_LCL_FLD:
9521             case GT_STORE_LCL_VAR:
9522                 if (tree->gtFlags & GTF_VAR_USEASG)
9523                 {
9524                     printf("U");
9525                     --msgLength;
9526                     break;
9527                 }
9528                 if (tree->gtFlags & GTF_VAR_DEF)
9529                 {
9530                     printf("D");
9531                     --msgLength;
9532                     break;
9533                 }
9534                 if (tree->gtFlags & GTF_VAR_CAST)
9535                 {
9536                     printf("C");
9537                     --msgLength;
9538                     break;
9539                 }
9540                 if (tree->gtFlags & GTF_VAR_ARR_INDEX)
9541                 {
9542                     printf("i");
9543                     --msgLength;
9544                     break;
9545                 }
9546                 goto DASH;
9547
9548             case GT_EQ:
9549             case GT_NE:
9550             case GT_LT:
9551             case GT_LE:
9552             case GT_GE:
9553             case GT_GT:
9554             case GT_TEST_EQ:
9555             case GT_TEST_NE:
9556                 if (tree->gtFlags & GTF_RELOP_NAN_UN)
9557                 {
9558                     printf("N");
9559                     --msgLength;
9560                     break;
9561                 }
9562                 if (tree->gtFlags & GTF_RELOP_JMP_USED)
9563                 {
9564                     printf("J");
9565                     --msgLength;
9566                     break;
9567                 }
9568                 if (tree->gtFlags & GTF_RELOP_QMARK)
9569                 {
9570                     printf("Q");
9571                     --msgLength;
9572                     break;
9573                 }
9574                 goto DASH;
9575
9576             case GT_JCMP:
9577                 printf((tree->gtFlags & GTF_JCMP_TST) ? "T" : "C");
9578                 printf((tree->gtFlags & GTF_JCMP_EQ) ? "EQ" : "NE");
9579                 goto DASH;
9580
9581             case GT_FIELD_LIST:
9582                 if (tree->gtFlags & GTF_FIELD_LIST_HEAD)
9583                 {
9584                     printf("H");
9585                     --msgLength;
9586                     break;
9587                 }
9588                 goto DASH;
9589
9590             default:
9591             DASH:
9592                 printf("-");
9593                 --msgLength;
9594                 break;
9595         }
9596
9597         /* Then print the general purpose flags */
9598         unsigned flags = tree->gtFlags;
9599
9600         if (tree->OperIsBinary())
9601         {
9602             genTreeOps oper = tree->OperGet();
9603
9604             // Check for GTF_ADDRMODE_NO_CSE flag on add/mul/shl Binary Operators
9605             if ((oper == GT_ADD) || (oper == GT_MUL) || (oper == GT_LSH))
9606             {
9607                 if ((tree->gtFlags & GTF_ADDRMODE_NO_CSE) != 0)
9608                 {
9609                     flags |= GTF_DONT_CSE; // Force the GTF_ADDRMODE_NO_CSE flag to print out like GTF_DONT_CSE
9610                 }
9611             }
9612         }
9613         else // !tree->OperIsBinary()
9614         {
9615             // the GTF_REVERSE flag only applies to binary operations
9616             flags &= ~GTF_REVERSE_OPS; // we use this value for GTF_VAR_ARR_INDEX above
9617         }
9618
9619         msgLength -= GenTree::gtDispFlags(flags, tree->gtDebugFlags);
9620         /*
9621             printf("%c", (flags & GTF_ASG           ) ? 'A' : '-');
9622             printf("%c", (flags & GTF_CALL          ) ? 'C' : '-');
9623             printf("%c", (flags & GTF_EXCEPT        ) ? 'X' : '-');
9624             printf("%c", (flags & GTF_GLOB_REF      ) ? 'G' : '-');
9625             printf("%c", (flags & GTF_ORDER_SIDEEFF ) ? 'O' : '-');
9626             printf("%c", (flags & GTF_COLON_COND    ) ? '?' : '-');
9627             printf("%c", (flags & GTF_DONT_CSE      ) ? 'N' :        // N is for No cse
9628                          (flags & GTF_MAKE_CSE      ) ? 'H' : '-');  // H is for Hoist this expr
9629             printf("%c", (flags & GTF_REVERSE_OPS   ) ? 'R' : '-');
9630             printf("%c", (flags & GTF_UNSIGNED      ) ? 'U' :
9631                          (flags & GTF_BOOLEAN       ) ? 'B' : '-');
9632             printf("%c", (flags & GTF_SET_FLAGS     ) ? 'S' : '-');
9633             printf("%c", (flags & GTF_SPILLED       ) ? 'z' : '-');
9634             printf("%c", (flags & GTF_SPILL         ) ? 'Z' : '-');
9635         */
9636     }
9637
9638     // If we're printing a node for LIR, we use the space normally associated with the message
9639     // to display the node's temp name (if any)
9640     const bool hasOperands = tree->OperandsBegin() != tree->OperandsEnd();
9641     if (isLIR)
9642     {
9643         assert(msg == nullptr);
9644
9645         // If the tree does not have any operands, we do not display the indent stack. This gives us
9646         // two additional characters for alignment.
9647         if (!hasOperands)
9648         {
9649             msgLength += 1;
9650         }
9651
9652         if (tree->IsValue())
9653         {
9654             const size_t bufLength = msgLength - 1;
9655             msg                    = reinterpret_cast<char*>(alloca(bufLength * sizeof(char)));
9656             sprintf_s(const_cast<char*>(msg), bufLength, "t%d = %s", tree->gtTreeID, hasOperands ? "" : " ");
9657         }
9658     }
9659
9660     /* print the msg associated with the node */
9661
9662     if (msg == nullptr)
9663     {
9664         msg = "";
9665     }
9666     if (msgLength < 0)
9667     {
9668         msgLength = 0;
9669     }
9670
9671     printf(isLIR ? " %+*s" : " %-*s", msgLength, msg);
9672
9673     /* Indent the node accordingly */
9674     if (!isLIR || hasOperands)
9675     {
9676         printIndent(indentStack);
9677     }
9678
9679     gtDispNodeName(tree);
9680
9681     assert(tree == nullptr || tree->gtOper < GT_COUNT);
9682
9683     if (tree)
9684     {
9685         /* print the type of the node */
9686         if (tree->gtOper != GT_CAST)
9687         {
9688             printf(" %-6s", varTypeName(tree->TypeGet()));
9689             if (tree->gtOper == GT_LCL_VAR || tree->gtOper == GT_STORE_LCL_VAR)
9690             {
9691                 LclVarDsc* varDsc = &lvaTable[tree->gtLclVarCommon.gtLclNum];
9692                 if (varDsc->lvAddrExposed)
9693                 {
9694                     printf("(AX)"); // Variable has address exposed.
9695                 }
9696
9697                 if (varDsc->lvUnusedStruct)
9698                 {
9699                     assert(varDsc->lvPromoted);
9700                     printf("(U)"); // Unused struct
9701                 }
9702                 else if (varDsc->lvPromoted)
9703                 {
9704                     if (varTypeIsPromotable(varDsc))
9705                     {
9706                         printf("(P)"); // Promoted struct
9707                     }
9708                     else
9709                     {
9710                         // Promoted implicit by-refs can have this state during
9711                         // global morph while they are being rewritten
9712                         assert(fgGlobalMorph);
9713                         printf("(P?!)"); // Promoted struct
9714                     }
9715                 }
9716             }
9717
9718             if (tree->gtOper == GT_STMT)
9719             {
9720                 if (opts.compDbgInfo)
9721                 {
9722                     IL_OFFSET endIL = tree->gtStmt.gtStmtLastILoffs;
9723
9724                     printf("(IL ");
9725                     if (tree->gtStmt.gtStmtILoffsx == BAD_IL_OFFSET)
9726                     {
9727                         printf("  ???");
9728                     }
9729                     else
9730                     {
9731                         printf("0x%03X", jitGetILoffs(tree->gtStmt.gtStmtILoffsx));
9732                     }
9733                     printf("...");
9734                     if (endIL == BAD_IL_OFFSET)
9735                     {
9736                         printf("  ???");
9737                     }
9738                     else
9739                     {
9740                         printf("0x%03X", endIL);
9741                     }
9742                     printf(")");
9743                 }
9744             }
9745
9746             if (tree->IsArgPlaceHolderNode() && (tree->gtArgPlace.gtArgPlaceClsHnd != nullptr))
9747             {
9748                 printf(" => [clsHnd=%08X]", dspPtr(tree->gtArgPlace.gtArgPlaceClsHnd));
9749             }
9750
9751             if (tree->gtOper == GT_RUNTIMELOOKUP)
9752             {
9753 #ifdef _TARGET_64BIT_
9754                 printf(" 0x%llx", dspPtr(tree->gtRuntimeLookup.gtHnd));
9755 #else
9756                 printf(" 0x%x", dspPtr(tree->gtRuntimeLookup.gtHnd));
9757 #endif
9758
9759                 switch (tree->gtRuntimeLookup.gtHndType)
9760                 {
9761                     case CORINFO_HANDLETYPE_CLASS:
9762                         printf(" class");
9763                         break;
9764                     case CORINFO_HANDLETYPE_METHOD:
9765                         printf(" method");
9766                         break;
9767                     case CORINFO_HANDLETYPE_FIELD:
9768                         printf(" field");
9769                         break;
9770                     default:
9771                         printf(" unknown");
9772                         break;
9773                 }
9774             }
9775         }
9776
9777         // for tracking down problems in reguse prediction or liveness tracking
9778
9779         if (verbose && 0)
9780         {
9781             printf(" RR=");
9782             dspRegMask(tree->gtRsvdRegs);
9783             printf("\n");
9784         }
9785     }
9786 }
9787
9788 void Compiler::gtDispRegVal(GenTree* tree)
9789 {
9790     switch (tree->GetRegTag())
9791     {
9792         // Don't display NOREG; the absence of this tag will imply this state
9793         // case GenTree::GT_REGTAG_NONE:       printf(" NOREG");   break;
9794
9795         case GenTree::GT_REGTAG_REG:
9796             printf(" REG %s", compRegVarName(tree->gtRegNum));
9797             break;
9798
9799         default:
9800             break;
9801     }
9802
9803     if (tree->IsMultiRegCall())
9804     {
9805         // 0th reg is gtRegNum, which is already printed above.
9806         // Print the remaining regs of a multi-reg call node.
9807         GenTreeCall* call     = tree->AsCall();
9808         unsigned     regCount = call->GetReturnTypeDesc()->TryGetReturnRegCount();
9809         for (unsigned i = 1; i < regCount; ++i)
9810         {
9811             printf(",%s", compRegVarName(call->GetRegNumByIdx(i)));
9812         }
9813     }
9814     else if (tree->IsCopyOrReloadOfMultiRegCall())
9815     {
9816         GenTreeCopyOrReload* copyOrReload = tree->AsCopyOrReload();
9817         GenTreeCall*         call         = tree->gtGetOp1()->AsCall();
9818         unsigned             regCount     = call->GetReturnTypeDesc()->TryGetReturnRegCount();
9819         for (unsigned i = 1; i < regCount; ++i)
9820         {
9821             printf(",%s", compRegVarName(copyOrReload->GetRegNumByIdx(i)));
9822         }
9823     }
9824
9825 #if FEATURE_MULTIREG_RET
9826     if (tree->IsCopyOrReload())
9827     {
9828         for (int i = 1; i < MAX_RET_REG_COUNT; i++)
9829         {
9830             regNumber reg = (regNumber)tree->AsCopyOrReload()->GetRegNumByIdx(i);
9831             if (reg == REG_NA)
9832             {
9833                 break;
9834             }
9835             printf(",%s", compRegVarName(reg));
9836         }
9837     }
9838 #endif
9839
9840 #if defined(_TARGET_ARM_)
9841     if (tree->OperIsMultiRegOp() && (tree->AsMultiRegOp()->gtOtherReg != REG_NA))
9842     {
9843         printf(",%s", compRegVarName(tree->AsMultiRegOp()->gtOtherReg));
9844     }
9845 #endif
9846 }
9847
9848 // We usually/commonly don't expect to print anything longer than this string,
9849 #define LONGEST_COMMON_LCL_VAR_DISPLAY "V99 PInvokeFrame"
9850 #define LONGEST_COMMON_LCL_VAR_DISPLAY_LENGTH (sizeof(LONGEST_COMMON_LCL_VAR_DISPLAY))
9851 #define BUF_SIZE (LONGEST_COMMON_LCL_VAR_DISPLAY_LENGTH * 2)
9852
9853 void Compiler::gtGetLclVarNameInfo(unsigned lclNum, const char** ilKindOut, const char** ilNameOut, unsigned* ilNumOut)
9854 {
9855     const char* ilKind = nullptr;
9856     const char* ilName = nullptr;
9857
9858     unsigned ilNum = compMap2ILvarNum(lclNum);
9859
9860     if (ilNum == (unsigned)ICorDebugInfo::RETBUF_ILNUM)
9861     {
9862         ilName = "RetBuf";
9863     }
9864     else if (ilNum == (unsigned)ICorDebugInfo::VARARGS_HND_ILNUM)
9865     {
9866         ilName = "VarArgHandle";
9867     }
9868     else if (ilNum == (unsigned)ICorDebugInfo::TYPECTXT_ILNUM)
9869     {
9870         ilName = "TypeCtx";
9871     }
9872     else if (ilNum == (unsigned)ICorDebugInfo::UNKNOWN_ILNUM)
9873     {
9874 #if FEATURE_ANYCSE
9875         if (lclNumIsTrueCSE(lclNum))
9876         {
9877             ilKind = "cse";
9878             ilNum  = lclNum - optCSEstart;
9879         }
9880         else if (lclNum >= optCSEstart)
9881         {
9882             // Currently any new LclVar's introduced after the CSE phase
9883             // are believed to be created by the "rationalizer" that is what is meant by the "rat" prefix.
9884             ilKind = "rat";
9885             ilNum  = lclNum - (optCSEstart + optCSEcount);
9886         }
9887         else
9888 #endif // FEATURE_ANYCSE
9889         {
9890             if (lclNum == info.compLvFrameListRoot)
9891             {
9892                 ilName = "FramesRoot";
9893             }
9894             else if (lclNum == lvaInlinedPInvokeFrameVar)
9895             {
9896                 ilName = "PInvokeFrame";
9897             }
9898             else if (lclNum == lvaGSSecurityCookie)
9899             {
9900                 ilName = "GsCookie";
9901             }
9902 #if FEATURE_FIXED_OUT_ARGS
9903             else if (lclNum == lvaPInvokeFrameRegSaveVar)
9904             {
9905                 ilName = "PInvokeFrameRegSave";
9906             }
9907             else if (lclNum == lvaOutgoingArgSpaceVar)
9908             {
9909                 ilName = "OutArgs";
9910             }
9911 #endif // FEATURE_FIXED_OUT_ARGS
9912 #ifdef _TARGET_ARM_
9913             else if (lclNum == lvaPromotedStructAssemblyScratchVar)
9914             {
9915                 ilName = "PromotedStructScratch";
9916             }
9917 #endif // _TARGET_ARM_
9918 #if !FEATURE_EH_FUNCLETS
9919             else if (lclNum == lvaShadowSPslotsVar)
9920             {
9921                 ilName = "EHSlots";
9922             }
9923 #endif // !FEATURE_EH_FUNCLETS
9924 #ifdef JIT32_GCENCODER
9925             else if (lclNum == lvaLocAllocSPvar)
9926             {
9927                 ilName = "LocAllocSP";
9928             }
9929 #endif // JIT32_GCENCODER
9930 #if FEATURE_EH_FUNCLETS
9931             else if (lclNum == lvaPSPSym)
9932             {
9933                 ilName = "PSPSym";
9934             }
9935 #endif // FEATURE_EH_FUNCLETS
9936             else
9937             {
9938                 ilKind = "tmp";
9939                 if (compIsForInlining())
9940                 {
9941                     ilNum = lclNum - impInlineInfo->InlinerCompiler->info.compLocalsCount;
9942                 }
9943                 else
9944                 {
9945                     ilNum = lclNum - info.compLocalsCount;
9946                 }
9947             }
9948         }
9949     }
9950     else if (lclNum < (compIsForInlining() ? impInlineInfo->InlinerCompiler->info.compArgsCount : info.compArgsCount))
9951     {
9952         if (ilNum == 0 && !info.compIsStatic)
9953         {
9954             ilName = "this";
9955         }
9956         else
9957         {
9958             ilKind = "arg";
9959         }
9960     }
9961     else
9962     {
9963         if (!lvaTable[lclNum].lvIsStructField)
9964         {
9965             ilKind = "loc";
9966         }
9967         if (compIsForInlining())
9968         {
9969             ilNum -= impInlineInfo->InlinerCompiler->info.compILargsCount;
9970         }
9971         else
9972         {
9973             ilNum -= info.compILargsCount;
9974         }
9975     }
9976
9977     *ilKindOut = ilKind;
9978     *ilNameOut = ilName;
9979     *ilNumOut  = ilNum;
9980 }
9981
9982 /*****************************************************************************/
9983 int Compiler::gtGetLclVarName(unsigned lclNum, char* buf, unsigned buf_remaining)
9984 {
9985     char*    bufp_next    = buf;
9986     unsigned charsPrinted = 0;
9987     int      sprintf_result;
9988
9989     sprintf_result = sprintf_s(bufp_next, buf_remaining, "V%02u", lclNum);
9990
9991     if (sprintf_result < 0)
9992     {
9993         return sprintf_result;
9994     }
9995
9996     charsPrinted += sprintf_result;
9997     bufp_next += sprintf_result;
9998     buf_remaining -= sprintf_result;
9999
10000     const char* ilKind = nullptr;
10001     const char* ilName = nullptr;
10002     unsigned    ilNum  = 0;
10003
10004     gtGetLclVarNameInfo(lclNum, &ilKind, &ilName, &ilNum);
10005
10006     if (ilName != nullptr)
10007     {
10008         sprintf_result = sprintf_s(bufp_next, buf_remaining, " %s", ilName);
10009         if (sprintf_result < 0)
10010         {
10011             return sprintf_result;
10012         }
10013         charsPrinted += sprintf_result;
10014         bufp_next += sprintf_result;
10015         buf_remaining -= sprintf_result;
10016     }
10017     else if (ilKind != nullptr)
10018     {
10019         sprintf_result = sprintf_s(bufp_next, buf_remaining, " %s%d", ilKind, ilNum);
10020         if (sprintf_result < 0)
10021         {
10022             return sprintf_result;
10023         }
10024         charsPrinted += sprintf_result;
10025         bufp_next += sprintf_result;
10026         buf_remaining -= sprintf_result;
10027     }
10028
10029     assert(charsPrinted > 0);
10030     assert(buf_remaining > 0);
10031
10032     return (int)charsPrinted;
10033 }
10034
10035 /*****************************************************************************
10036  * Get the local var name, and create a copy of the string that can be used in debug output.
10037  */
10038 char* Compiler::gtGetLclVarName(unsigned lclNum)
10039 {
10040     char buf[BUF_SIZE];
10041     int  charsPrinted = gtGetLclVarName(lclNum, buf, _countof(buf));
10042     if (charsPrinted < 0)
10043     {
10044         return nullptr;
10045     }
10046
10047     char* retBuf = new (this, CMK_DebugOnly) char[charsPrinted + 1];
10048     strcpy_s(retBuf, charsPrinted + 1, buf);
10049     return retBuf;
10050 }
10051
10052 /*****************************************************************************/
10053 void Compiler::gtDispLclVar(unsigned lclNum, bool padForBiggestDisp)
10054 {
10055     char buf[BUF_SIZE];
10056     int  charsPrinted = gtGetLclVarName(lclNum, buf, _countof(buf));
10057
10058     if (charsPrinted < 0)
10059     {
10060         return;
10061     }
10062
10063     printf("%s", buf);
10064
10065     if (padForBiggestDisp && (charsPrinted < LONGEST_COMMON_LCL_VAR_DISPLAY_LENGTH))
10066     {
10067         printf("%*c", LONGEST_COMMON_LCL_VAR_DISPLAY_LENGTH - charsPrinted, ' ');
10068     }
10069 }
10070
10071 /*****************************************************************************/
10072 void Compiler::gtDispConst(GenTree* tree)
10073 {
10074     assert(tree->OperKind() & GTK_CONST);
10075
10076     switch (tree->gtOper)
10077     {
10078         case GT_CNS_INT:
10079             if (tree->IsIconHandle(GTF_ICON_STR_HDL))
10080             {
10081                 const wchar_t* str = eeGetCPString(tree->gtIntCon.gtIconVal);
10082                 if (str != nullptr)
10083                 {
10084                     printf(" 0x%X \"%S\"", dspPtr(tree->gtIntCon.gtIconVal), str);
10085                 }
10086                 else
10087                 {
10088                     // Note that eGetCPString isn't currently implemented on Linux/ARM
10089                     // and instead always returns nullptr
10090                     printf(" 0x%X [ICON_STR_HDL]", dspPtr(tree->gtIntCon.gtIconVal));
10091                 }
10092             }
10093             else
10094             {
10095                 ssize_t dspIconVal = tree->IsIconHandle() ? dspPtr(tree->gtIntCon.gtIconVal) : tree->gtIntCon.gtIconVal;
10096
10097                 if (tree->TypeGet() == TYP_REF)
10098                 {
10099                     assert(tree->gtIntCon.gtIconVal == 0);
10100                     printf(" null");
10101                 }
10102                 else if ((tree->gtIntCon.gtIconVal > -1000) && (tree->gtIntCon.gtIconVal < 1000))
10103                 {
10104                     printf(" %ld", dspIconVal);
10105 #ifdef _TARGET_64BIT_
10106                 }
10107                 else if ((tree->gtIntCon.gtIconVal & 0xFFFFFFFF00000000LL) != 0)
10108                 {
10109                     printf(" 0x%llx", dspIconVal);
10110 #endif
10111                 }
10112                 else
10113                 {
10114                     printf(" 0x%X", dspIconVal);
10115                 }
10116
10117                 if (tree->IsIconHandle())
10118                 {
10119                     switch (tree->GetIconHandleFlag())
10120                     {
10121                         case GTF_ICON_SCOPE_HDL:
10122                             printf(" scope");
10123                             break;
10124                         case GTF_ICON_CLASS_HDL:
10125                             printf(" class");
10126                             break;
10127                         case GTF_ICON_METHOD_HDL:
10128                             printf(" method");
10129                             break;
10130                         case GTF_ICON_FIELD_HDL:
10131                             printf(" field");
10132                             break;
10133                         case GTF_ICON_STATIC_HDL:
10134                             printf(" static");
10135                             break;
10136                         case GTF_ICON_STR_HDL:
10137                             unreached(); // This case is handled above
10138                             break;
10139                         case GTF_ICON_PSTR_HDL:
10140                             printf(" pstr");
10141                             break;
10142                         case GTF_ICON_PTR_HDL:
10143                             printf(" ptr");
10144                             break;
10145                         case GTF_ICON_VARG_HDL:
10146                             printf(" vararg");
10147                             break;
10148                         case GTF_ICON_PINVKI_HDL:
10149                             printf(" pinvoke");
10150                             break;
10151                         case GTF_ICON_TOKEN_HDL:
10152                             printf(" token");
10153                             break;
10154                         case GTF_ICON_TLS_HDL:
10155                             printf(" tls");
10156                             break;
10157                         case GTF_ICON_FTN_ADDR:
10158                             printf(" ftn");
10159                             break;
10160                         case GTF_ICON_CIDMID_HDL:
10161                             printf(" cid/mid");
10162                             break;
10163                         case GTF_ICON_BBC_PTR:
10164                             printf(" bbc");
10165                             break;
10166                         default:
10167                             printf(" UNKNOWN");
10168                             break;
10169                     }
10170                 }
10171
10172                 if ((tree->gtFlags & GTF_ICON_FIELD_OFF) != 0)
10173                 {
10174                     printf(" field offset");
10175                 }
10176
10177 #ifdef FEATURE_SIMD
10178                 if ((tree->gtFlags & GTF_ICON_SIMD_COUNT) != 0)
10179                 {
10180                     printf(" Vector<T>.Count");
10181                 }
10182 #endif
10183
10184                 if ((tree->IsReuseRegVal()) != 0)
10185                 {
10186                     printf(" reuse reg val");
10187                 }
10188             }
10189
10190             gtDispFieldSeq(tree->gtIntCon.gtFieldSeq);
10191
10192             break;
10193
10194         case GT_CNS_LNG:
10195             printf(" 0x%016I64x", tree->gtLngCon.gtLconVal);
10196             break;
10197
10198         case GT_CNS_DBL:
10199             if (*((__int64*)&tree->gtDblCon.gtDconVal) == (__int64)I64(0x8000000000000000))
10200             {
10201                 printf(" -0.00000");
10202             }
10203             else
10204             {
10205                 printf(" %#.17g", tree->gtDblCon.gtDconVal);
10206             }
10207             break;
10208         case GT_CNS_STR:
10209             printf("<string constant>");
10210             break;
10211         default:
10212             assert(!"unexpected constant node");
10213     }
10214
10215     gtDispRegVal(tree);
10216 }
10217
10218 void Compiler::gtDispFieldSeq(FieldSeqNode* pfsn)
10219 {
10220     if (pfsn == FieldSeqStore::NotAField() || (pfsn == nullptr))
10221     {
10222         return;
10223     }
10224
10225     // Otherwise...
10226     printf(" Fseq[");
10227     while (pfsn != nullptr)
10228     {
10229         assert(pfsn != FieldSeqStore::NotAField()); // Can't exist in a field sequence list except alone
10230         CORINFO_FIELD_HANDLE fldHnd = pfsn->m_fieldHnd;
10231         // First check the "pseudo" field handles...
10232         if (fldHnd == FieldSeqStore::FirstElemPseudoField)
10233         {
10234             printf("#FirstElem");
10235         }
10236         else if (fldHnd == FieldSeqStore::ConstantIndexPseudoField)
10237         {
10238             printf("#ConstantIndex");
10239         }
10240         else
10241         {
10242             printf("%s", eeGetFieldName(fldHnd));
10243         }
10244         pfsn = pfsn->m_next;
10245         if (pfsn != nullptr)
10246         {
10247             printf(", ");
10248         }
10249     }
10250     printf("]");
10251 }
10252
10253 //------------------------------------------------------------------------
10254 // gtDispLeaf: Print a single leaf node to jitstdout.
10255 //
10256 // Arguments:
10257 //    tree - the tree to be printed
10258 //    indentStack - the specification for the current level of indentation & arcs
10259 //
10260 // Return Value:
10261 //    None.
10262 //
10263 // Notes:
10264 //    'indentStack' may be null, in which case no indentation or arcs are printed
10265
10266 void Compiler::gtDispLeaf(GenTree* tree, IndentStack* indentStack)
10267 {
10268     if (tree->OperKind() & GTK_CONST)
10269     {
10270         gtDispConst(tree);
10271         return;
10272     }
10273
10274     bool isLclFld = false;
10275
10276     switch (tree->gtOper)
10277     {
10278         unsigned   varNum;
10279         LclVarDsc* varDsc;
10280
10281         case GT_LCL_FLD:
10282         case GT_LCL_FLD_ADDR:
10283         case GT_STORE_LCL_FLD:
10284             isLclFld = true;
10285             __fallthrough;
10286
10287         case GT_PHI_ARG:
10288         case GT_LCL_VAR:
10289         case GT_LCL_VAR_ADDR:
10290         case GT_STORE_LCL_VAR:
10291             printf(" ");
10292             varNum = tree->gtLclVarCommon.gtLclNum;
10293             varDsc = &lvaTable[varNum];
10294             gtDispLclVar(varNum);
10295             if (tree->gtLclVarCommon.HasSsaName())
10296             {
10297                 if (tree->gtFlags & GTF_VAR_USEASG)
10298                 {
10299                     assert(tree->gtFlags & GTF_VAR_DEF);
10300                     printf("ud:%d->%d", tree->gtLclVarCommon.gtSsaNum, GetSsaNumForLocalVarDef(tree));
10301                 }
10302                 else
10303                 {
10304                     printf("%s:%d", (tree->gtFlags & GTF_VAR_DEF) ? "d" : "u", tree->gtLclVarCommon.gtSsaNum);
10305                 }
10306             }
10307
10308             if (isLclFld)
10309             {
10310                 printf("[+%u]", tree->gtLclFld.gtLclOffs);
10311                 gtDispFieldSeq(tree->gtLclFld.gtFieldSeq);
10312             }
10313
10314             if (varDsc->lvRegister)
10315             {
10316                 printf(" ");
10317                 varDsc->PrintVarReg();
10318             }
10319             else if (tree->InReg())
10320             {
10321                 printf(" %s", compRegVarName(tree->gtRegNum));
10322             }
10323
10324             if (varDsc->lvPromoted)
10325             {
10326                 if (!varTypeIsPromotable(varDsc) && !varDsc->lvUnusedStruct)
10327                 {
10328                     // Promoted implicit byrefs can get in this state while they are being rewritten
10329                     // in global morph.
10330                     assert(fgGlobalMorph);
10331                 }
10332                 else
10333                 {
10334                     CORINFO_CLASS_HANDLE typeHnd = varDsc->lvVerTypeInfo.GetClassHandle();
10335                     CORINFO_FIELD_HANDLE fldHnd;
10336
10337                     for (unsigned i = varDsc->lvFieldLclStart; i < varDsc->lvFieldLclStart + varDsc->lvFieldCnt; ++i)
10338                     {
10339                         LclVarDsc*  fieldVarDsc = &lvaTable[i];
10340                         const char* fieldName;
10341 #if !defined(_TARGET_64BIT_)
10342                         if (varTypeIsLong(varDsc))
10343                         {
10344                             fieldName = (i == 0) ? "lo" : "hi";
10345                         }
10346                         else
10347 #endif // !defined(_TARGET_64BIT_)
10348                         {
10349                             fldHnd    = info.compCompHnd->getFieldInClass(typeHnd, fieldVarDsc->lvFldOrdinal);
10350                             fieldName = eeGetFieldName(fldHnd);
10351                         }
10352
10353                         printf("\n");
10354                         printf("                                                  ");
10355                         printIndent(indentStack);
10356                         printf("    %-6s V%02u.%s (offs=0x%02x) -> ", varTypeName(fieldVarDsc->TypeGet()),
10357                                tree->gtLclVarCommon.gtLclNum, fieldName, fieldVarDsc->lvFldOffset);
10358                         gtDispLclVar(i);
10359
10360                         if (fieldVarDsc->lvRegister)
10361                         {
10362                             printf(" ");
10363                             fieldVarDsc->PrintVarReg();
10364                         }
10365
10366                         if (fieldVarDsc->lvTracked && fgLocalVarLivenessDone && // Includes local variable liveness
10367                             ((tree->gtFlags & GTF_VAR_DEATH) != 0))
10368                         {
10369                             printf(" (last use)");
10370                         }
10371                     }
10372                 }
10373             }
10374             else // a normal not-promoted lclvar
10375             {
10376                 if (varDsc->lvTracked && fgLocalVarLivenessDone && ((tree->gtFlags & GTF_VAR_DEATH) != 0))
10377                 {
10378                     printf(" (last use)");
10379                 }
10380             }
10381             break;
10382
10383         case GT_JMP:
10384         {
10385             const char* methodName;
10386             const char* className;
10387
10388             methodName = eeGetMethodName((CORINFO_METHOD_HANDLE)tree->gtVal.gtVal1, &className);
10389             printf(" %s.%s\n", className, methodName);
10390         }
10391         break;
10392
10393         case GT_CLS_VAR:
10394             printf(" Hnd=%#x", dspPtr(tree->gtClsVar.gtClsVarHnd));
10395             gtDispFieldSeq(tree->gtClsVar.gtFieldSeq);
10396             break;
10397
10398         case GT_CLS_VAR_ADDR:
10399             printf(" Hnd=%#x", dspPtr(tree->gtClsVar.gtClsVarHnd));
10400             break;
10401
10402         case GT_LABEL:
10403             if (tree->gtLabel.gtLabBB)
10404             {
10405                 printf(" dst=" FMT_BB, tree->gtLabel.gtLabBB->bbNum);
10406             }
10407             else
10408             {
10409                 printf(" dst=<null>");
10410             }
10411
10412             break;
10413
10414         case GT_FTN_ADDR:
10415         {
10416             const char* methodName;
10417             const char* className;
10418
10419             methodName = eeGetMethodName((CORINFO_METHOD_HANDLE)tree->gtFptrVal.gtFptrMethod, &className);
10420             printf(" %s.%s\n", className, methodName);
10421         }
10422         break;
10423
10424 #if !FEATURE_EH_FUNCLETS
10425         case GT_END_LFIN:
10426             printf(" endNstLvl=%d", tree->gtVal.gtVal1);
10427             break;
10428 #endif // !FEATURE_EH_FUNCLETS
10429
10430         // Vanilla leaves. No qualifying information available. So do nothing
10431
10432         case GT_NO_OP:
10433         case GT_START_NONGC:
10434         case GT_PROF_HOOK:
10435         case GT_CATCH_ARG:
10436         case GT_MEMORYBARRIER:
10437         case GT_ARGPLACE:
10438         case GT_PINVOKE_PROLOG:
10439         case GT_JMPTABLE:
10440             break;
10441
10442         case GT_RET_EXPR:
10443             printf("(inl return from call ");
10444             printTreeID(tree->gtRetExpr.gtInlineCandidate);
10445             printf(")");
10446             break;
10447
10448         case GT_PHYSREG:
10449             printf(" %s", getRegName(tree->gtPhysReg.gtSrcReg, varTypeIsFloating(tree)));
10450             break;
10451
10452         case GT_IL_OFFSET:
10453             printf(" IL offset: ");
10454             if (tree->gtStmt.gtStmtILoffsx == BAD_IL_OFFSET)
10455             {
10456                 printf("???");
10457             }
10458             else
10459             {
10460                 printf("0x%x", jitGetILoffs(tree->gtStmt.gtStmtILoffsx));
10461             }
10462             break;
10463
10464         case GT_JCC:
10465         case GT_SETCC:
10466             printf(" cond=%s", GenTree::OpName(tree->AsCC()->gtCondition));
10467             break;
10468         case GT_JCMP:
10469             printf(" cond=%s%s", (tree->gtFlags & GTF_JCMP_TST) ? "TEST_" : "",
10470                    (tree->gtFlags & GTF_JCMP_EQ) ? "EQ" : "NE");
10471
10472         default:
10473             assert(!"don't know how to display tree leaf node");
10474     }
10475
10476     gtDispRegVal(tree);
10477 }
10478
10479 //------------------------------------------------------------------------
10480 // gtDispLeaf: Print a child node to jitstdout.
10481 //
10482 // Arguments:
10483 //    tree - the tree to be printed
10484 //    indentStack - the specification for the current level of indentation & arcs
10485 //    arcType     - the type of arc to use for this child
10486 //    msg         - a contextual method (i.e. from the parent) to print
10487 //    topOnly     - a boolean indicating whether to print the children, or just the top node
10488 //
10489 // Return Value:
10490 //    None.
10491 //
10492 // Notes:
10493 //    'indentStack' may be null, in which case no indentation or arcs are printed
10494 //    'msg' has a default value of null
10495 //    'topOnly' is an optional argument that defaults to false
10496
10497 void Compiler::gtDispChild(GenTree*             child,
10498                            IndentStack*         indentStack,
10499                            IndentInfo           arcType,
10500                            __in_opt const char* msg,     /* = nullptr  */
10501                            bool                 topOnly) /* = false */
10502 {
10503     indentStack->Push(arcType);
10504     gtDispTree(child, indentStack, msg, topOnly);
10505     indentStack->Pop();
10506 }
10507
10508 #ifdef FEATURE_SIMD
10509 // Intrinsic Id to name map
10510 extern const char* const simdIntrinsicNames[] = {
10511 #define SIMD_INTRINSIC(mname, inst, id, name, r, ac, arg1, arg2, arg3, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10) name,
10512 #include "simdintrinsiclist.h"
10513 };
10514 #endif // FEATURE_SIMD
10515
10516 /*****************************************************************************/
10517
10518 void Compiler::gtDispTree(GenTree*     tree,
10519                           IndentStack* indentStack,                 /* = nullptr */
10520                           __in __in_z __in_opt const char* msg,     /* = nullptr  */
10521                           bool                             topOnly, /* = false */
10522                           bool                             isLIR)   /* = false */
10523 {
10524     if (tree == nullptr)
10525     {
10526         printf(" [%08X] <NULL>\n", tree);
10527         printf(""); // null string means flush
10528         return;
10529     }
10530
10531     if (indentStack == nullptr)
10532     {
10533         indentStack = new (this, CMK_DebugOnly) IndentStack(this);
10534     }
10535
10536     if (IsUninitialized(tree))
10537     {
10538         /* Value used to initalize nodes */
10539         printf("Uninitialized tree node!");
10540         return;
10541     }
10542
10543     if (tree->gtOper >= GT_COUNT)
10544     {
10545         gtDispNode(tree, indentStack, msg, isLIR);
10546         printf("Bogus operator!");
10547         return;
10548     }
10549
10550     /* Is tree a leaf node? */
10551
10552     if (tree->OperIsLeaf() || tree->OperIsLocalStore()) // local stores used to be leaves
10553     {
10554         gtDispNode(tree, indentStack, msg, isLIR);
10555         gtDispLeaf(tree, indentStack);
10556         gtDispVN(tree);
10557         printf("\n");
10558         if (tree->OperIsLocalStore() && !topOnly)
10559         {
10560             gtDispChild(tree->gtOp.gtOp1, indentStack, IINone);
10561         }
10562         return;
10563     }
10564
10565     // Determine what kind of arc to propagate.
10566     IndentInfo myArc    = IINone;
10567     IndentInfo lowerArc = IINone;
10568     if (indentStack->Depth() > 0)
10569     {
10570         myArc = indentStack->Pop();
10571         switch (myArc)
10572         {
10573             case IIArcBottom:
10574                 indentStack->Push(IIArc);
10575                 lowerArc = IINone;
10576                 break;
10577             case IIArc:
10578                 indentStack->Push(IIArc);
10579                 lowerArc = IIArc;
10580                 break;
10581             case IIArcTop:
10582                 indentStack->Push(IINone);
10583                 lowerArc = IIArc;
10584                 break;
10585             case IIEmbedded:
10586                 indentStack->Push(IIEmbedded);
10587                 lowerArc = IIEmbedded;
10588                 break;
10589             case IINone:
10590                 indentStack->Push(IINone);
10591                 lowerArc = IINone;
10592                 break;
10593             default:
10594                 unreached();
10595                 break;
10596         }
10597     }
10598
10599     // Special case formatting for PHI nodes -- arg lists like calls.
10600
10601     if (tree->OperGet() == GT_PHI)
10602     {
10603         gtDispNode(tree, indentStack, msg, isLIR);
10604         gtDispVN(tree);
10605         printf("\n");
10606
10607         if (!topOnly)
10608         {
10609             if (tree->gtOp.gtOp1 != nullptr)
10610             {
10611                 IndentInfo arcType = IIArcTop;
10612                 for (GenTreeArgList* args = tree->gtOp.gtOp1->AsArgList(); args != nullptr; args = args->Rest())
10613                 {
10614                     if (args->Rest() == nullptr)
10615                     {
10616                         arcType = IIArcBottom;
10617                     }
10618                     gtDispChild(args->Current(), indentStack, arcType);
10619                     arcType = IIArc;
10620                 }
10621             }
10622         }
10623         return;
10624     }
10625
10626     /* Is it a 'simple' unary/binary operator? */
10627
10628     const char* childMsg = nullptr;
10629
10630     if (tree->OperIsSimple())
10631     {
10632         if (!topOnly)
10633         {
10634             if (tree->gtGetOp2IfPresent())
10635             {
10636                 // Label the childMsgs of the GT_COLON operator
10637                 // op2 is the then part
10638
10639                 if (tree->gtOper == GT_COLON)
10640                 {
10641                     childMsg = "then";
10642                 }
10643                 gtDispChild(tree->gtOp.gtOp2, indentStack, IIArcTop, childMsg, topOnly);
10644             }
10645         }
10646
10647         // Now, get the right type of arc for this node
10648         if (myArc != IINone)
10649         {
10650             indentStack->Pop();
10651             indentStack->Push(myArc);
10652         }
10653
10654         gtDispNode(tree, indentStack, msg, isLIR);
10655
10656         // Propagate lowerArc to the lower children.
10657         if (indentStack->Depth() > 0)
10658         {
10659             (void)indentStack->Pop();
10660             indentStack->Push(lowerArc);
10661         }
10662
10663         if (tree->gtOper == GT_CAST)
10664         {
10665             /* Format a message that explains the effect of this GT_CAST */
10666
10667             var_types fromType  = genActualType(tree->gtCast.CastOp()->TypeGet());
10668             var_types toType    = tree->CastToType();
10669             var_types finalType = tree->TypeGet();
10670
10671             /* if GTF_UNSIGNED is set then force fromType to an unsigned type */
10672             if (tree->gtFlags & GTF_UNSIGNED)
10673             {
10674                 fromType = genUnsignedType(fromType);
10675             }
10676
10677             if (finalType != toType)
10678             {
10679                 printf(" %s <-", varTypeName(finalType));
10680             }
10681
10682             printf(" %s <- %s", varTypeName(toType), varTypeName(fromType));
10683         }
10684
10685         if (tree->gtOper == GT_OBJ && (tree->gtFlags & GTF_VAR_DEATH))
10686         {
10687             printf(" (last use)");
10688         }
10689         if (tree->OperIsBlkOp())
10690         {
10691             if (tree->OperIsCopyBlkOp())
10692             {
10693                 printf(" (copy)");
10694             }
10695             else if (tree->OperIsInitBlkOp())
10696             {
10697                 printf(" (init)");
10698             }
10699             if (tree->OperIsStoreBlk() && (tree->AsBlk()->gtBlkOpKind != GenTreeBlk::BlkOpKindInvalid))
10700             {
10701                 switch (tree->AsBlk()->gtBlkOpKind)
10702                 {
10703                     case GenTreeBlk::BlkOpKindRepInstr:
10704                         printf(" (RepInstr)");
10705                         break;
10706                     case GenTreeBlk::BlkOpKindUnroll:
10707                         printf(" (Unroll)");
10708                         break;
10709                     case GenTreeBlk::BlkOpKindHelper:
10710                         printf(" (Helper)");
10711                         break;
10712                     default:
10713                         unreached();
10714                 }
10715             }
10716         }
10717         else if (tree->OperIsFieldList())
10718         {
10719             printf(" %s at offset %d", varTypeName(tree->AsFieldList()->gtFieldType),
10720                    tree->AsFieldList()->gtFieldOffset);
10721         }
10722 #if FEATURE_PUT_STRUCT_ARG_STK
10723         else if (tree->OperGet() == GT_PUTARG_STK)
10724         {
10725             printf(" (%d slots)", tree->AsPutArgStk()->gtNumSlots);
10726             if (tree->AsPutArgStk()->gtPutArgStkKind != GenTreePutArgStk::Kind::Invalid)
10727             {
10728                 switch (tree->AsPutArgStk()->gtPutArgStkKind)
10729                 {
10730                     case GenTreePutArgStk::Kind::RepInstr:
10731                         printf(" (RepInstr)");
10732                         break;
10733                     case GenTreePutArgStk::Kind::Unroll:
10734                         printf(" (Unroll)");
10735                         break;
10736                     case GenTreePutArgStk::Kind::Push:
10737                         printf(" (Push)");
10738                         break;
10739                     case GenTreePutArgStk::Kind::PushAllSlots:
10740                         printf(" (PushAllSlots)");
10741                         break;
10742                     default:
10743                         unreached();
10744                 }
10745             }
10746         }
10747 #endif // FEATURE_PUT_STRUCT_ARG_STK
10748
10749         if (tree->gtOper == GT_INTRINSIC)
10750         {
10751             switch (tree->gtIntrinsic.gtIntrinsicId)
10752             {
10753                 case CORINFO_INTRINSIC_Sin:
10754                     printf(" sin");
10755                     break;
10756                 case CORINFO_INTRINSIC_Cos:
10757                     printf(" cos");
10758                     break;
10759                 case CORINFO_INTRINSIC_Cbrt:
10760                     printf(" cbrt");
10761                     break;
10762                 case CORINFO_INTRINSIC_Sqrt:
10763                     printf(" sqrt");
10764                     break;
10765                 case CORINFO_INTRINSIC_Abs:
10766                     printf(" abs");
10767                     break;
10768                 case CORINFO_INTRINSIC_Round:
10769                     printf(" round");
10770                     break;
10771                 case CORINFO_INTRINSIC_Cosh:
10772                     printf(" cosh");
10773                     break;
10774                 case CORINFO_INTRINSIC_Sinh:
10775                     printf(" sinh");
10776                     break;
10777                 case CORINFO_INTRINSIC_Tan:
10778                     printf(" tan");
10779                     break;
10780                 case CORINFO_INTRINSIC_Tanh:
10781                     printf(" tanh");
10782                     break;
10783                 case CORINFO_INTRINSIC_Asin:
10784                     printf(" asin");
10785                     break;
10786                 case CORINFO_INTRINSIC_Asinh:
10787                     printf(" asinh");
10788                     break;
10789                 case CORINFO_INTRINSIC_Acos:
10790                     printf(" acos");
10791                     break;
10792                 case CORINFO_INTRINSIC_Acosh:
10793                     printf(" acosh");
10794                     break;
10795                 case CORINFO_INTRINSIC_Atan:
10796                     printf(" atan");
10797                     break;
10798                 case CORINFO_INTRINSIC_Atan2:
10799                     printf(" atan2");
10800                     break;
10801                 case CORINFO_INTRINSIC_Atanh:
10802                     printf(" atanh");
10803                     break;
10804                 case CORINFO_INTRINSIC_Log10:
10805                     printf(" log10");
10806                     break;
10807                 case CORINFO_INTRINSIC_Pow:
10808                     printf(" pow");
10809                     break;
10810                 case CORINFO_INTRINSIC_Exp:
10811                     printf(" exp");
10812                     break;
10813                 case CORINFO_INTRINSIC_Ceiling:
10814                     printf(" ceiling");
10815                     break;
10816                 case CORINFO_INTRINSIC_Floor:
10817                     printf(" floor");
10818                     break;
10819                 case CORINFO_INTRINSIC_Object_GetType:
10820                     printf(" objGetType");
10821                     break;
10822
10823                 default:
10824                     unreached();
10825             }
10826         }
10827
10828 #ifdef FEATURE_SIMD
10829         if (tree->gtOper == GT_SIMD)
10830         {
10831             printf(" %s %s", varTypeName(tree->gtSIMD.gtSIMDBaseType),
10832                    simdIntrinsicNames[tree->gtSIMD.gtSIMDIntrinsicID]);
10833         }
10834 #endif // FEATURE_SIMD
10835
10836 #ifdef FEATURE_HW_INTRINSICS
10837         if (tree->gtOper == GT_HWIntrinsic)
10838         {
10839             printf(" %s %s",
10840                    tree->gtHWIntrinsic.gtSIMDBaseType == TYP_UNKNOWN ? ""
10841                                                                      : varTypeName(tree->gtHWIntrinsic.gtSIMDBaseType),
10842                    HWIntrinsicInfo::lookupName(tree->gtHWIntrinsic.gtHWIntrinsicId));
10843         }
10844 #endif // FEATURE_HW_INTRINSICS
10845
10846         gtDispRegVal(tree);
10847         gtDispVN(tree);
10848         printf("\n");
10849
10850         if (!topOnly && tree->gtOp.gtOp1)
10851         {
10852
10853             // Label the child of the GT_COLON operator
10854             // op1 is the else part
10855
10856             if (tree->gtOper == GT_COLON)
10857             {
10858                 childMsg = "else";
10859             }
10860             else if (tree->gtOper == GT_QMARK)
10861             {
10862                 childMsg = "   if";
10863             }
10864             gtDispChild(tree->gtOp.gtOp1, indentStack, IIArcBottom, childMsg, topOnly);
10865         }
10866
10867         return;
10868     }
10869
10870     // Now, get the right type of arc for this node
10871     if (myArc != IINone)
10872     {
10873         indentStack->Pop();
10874         indentStack->Push(myArc);
10875     }
10876     gtDispNode(tree, indentStack, msg, isLIR);
10877
10878     // Propagate lowerArc to the lower children.
10879     if (indentStack->Depth() > 0)
10880     {
10881         (void)indentStack->Pop();
10882         indentStack->Push(lowerArc);
10883     }
10884
10885     // See what kind of a special operator we have here, and handle its special children.
10886
10887     switch (tree->gtOper)
10888     {
10889         case GT_FIELD:
10890             if (FieldSeqStore::IsPseudoField(tree->gtField.gtFldHnd))
10891             {
10892                 printf(" #PseudoField:0x%x", tree->gtField.gtFldOffset);
10893             }
10894             else
10895             {
10896                 printf(" %s", eeGetFieldName(tree->gtField.gtFldHnd), 0);
10897             }
10898
10899             if (tree->gtField.gtFldObj && !topOnly)
10900             {
10901                 gtDispVN(tree);
10902                 printf("\n");
10903                 gtDispChild(tree->gtField.gtFldObj, indentStack, IIArcBottom);
10904             }
10905             else
10906             {
10907                 gtDispRegVal(tree);
10908                 gtDispVN(tree);
10909                 printf("\n");
10910             }
10911             break;
10912
10913         case GT_CALL:
10914         {
10915             GenTreeCall* call = tree->AsCall();
10916             assert(call->gtFlags & GTF_CALL);
10917             unsigned numChildren = call->NumChildren();
10918             GenTree* lastChild   = nullptr;
10919             if (numChildren != 0)
10920             {
10921                 lastChild = call->GetChild(numChildren - 1);
10922             }
10923
10924             if (call->gtCallType != CT_INDIRECT)
10925             {
10926                 const char* methodName;
10927                 const char* className;
10928
10929                 methodName = eeGetMethodName(call->gtCallMethHnd, &className);
10930
10931                 printf(" %s.%s", className, methodName);
10932             }
10933
10934             if ((call->gtFlags & GTF_CALL_UNMANAGED) && (call->gtCallMoreFlags & GTF_CALL_M_FRAME_VAR_DEATH))
10935             {
10936                 printf(" (FramesRoot last use)");
10937             }
10938
10939             if (((call->gtFlags & GTF_CALL_INLINE_CANDIDATE) != 0) && (call->gtInlineCandidateInfo != nullptr) &&
10940                 (call->gtInlineCandidateInfo->exactContextHnd != nullptr))
10941             {
10942                 printf(" (exactContextHnd=0x%p)", dspPtr(call->gtInlineCandidateInfo->exactContextHnd));
10943             }
10944
10945             gtDispVN(call);
10946             if (call->IsMultiRegCall())
10947             {
10948                 gtDispRegVal(call);
10949             }
10950             printf("\n");
10951
10952             if (!topOnly)
10953             {
10954                 char  buf[64];
10955                 char* bufp;
10956
10957                 bufp = &buf[0];
10958
10959                 if ((call->gtCallObjp != nullptr) && (call->gtCallObjp->gtOper != GT_NOP) &&
10960                     (!call->gtCallObjp->IsArgPlaceHolderNode()))
10961                 {
10962                     if (call->gtCallObjp->gtOper == GT_ASG)
10963                     {
10964                         sprintf_s(bufp, sizeof(buf), "this SETUP%c", 0);
10965                     }
10966                     else
10967                     {
10968                         sprintf_s(bufp, sizeof(buf), "this in %s%c", compRegVarName(REG_ARG_0), 0);
10969                     }
10970                     gtDispChild(call->gtCallObjp, indentStack, (call->gtCallObjp == lastChild) ? IIArcBottom : IIArc,
10971                                 bufp, topOnly);
10972                 }
10973
10974                 if (call->gtCallArgs)
10975                 {
10976                     gtDispArgList(call, indentStack);
10977                 }
10978
10979                 if (call->gtCallType == CT_INDIRECT)
10980                 {
10981                     gtDispChild(call->gtCallAddr, indentStack, (call->gtCallAddr == lastChild) ? IIArcBottom : IIArc,
10982                                 "calli tgt", topOnly);
10983                 }
10984
10985                 if (call->gtControlExpr != nullptr)
10986                 {
10987                     gtDispChild(call->gtControlExpr, indentStack,
10988                                 (call->gtControlExpr == lastChild) ? IIArcBottom : IIArc, "control expr", topOnly);
10989                 }
10990
10991 #if !FEATURE_FIXED_OUT_ARGS
10992                 regList list = call->regArgList;
10993 #endif
10994                 /* process the late argument list */
10995                 int lateArgIndex = 0;
10996                 for (GenTreeArgList* lateArgs = call->gtCallLateArgs; lateArgs;
10997                      (lateArgIndex++, lateArgs = lateArgs->Rest()))
10998                 {
10999                     GenTree* argx;
11000
11001                     argx = lateArgs->Current();
11002
11003                     IndentInfo arcType = (lateArgs->Rest() == nullptr) ? IIArcBottom : IIArc;
11004                     gtGetLateArgMsg(call, argx, lateArgIndex, -1, bufp, sizeof(buf));
11005                     gtDispChild(argx, indentStack, arcType, bufp, topOnly);
11006                 }
11007             }
11008         }
11009         break;
11010
11011         case GT_STMT:
11012             printf("\n");
11013
11014             if (!topOnly)
11015             {
11016                 gtDispChild(tree->gtStmt.gtStmtExpr, indentStack, IIArcBottom);
11017             }
11018             break;
11019
11020         case GT_ARR_ELEM:
11021             gtDispVN(tree);
11022             printf("\n");
11023
11024             if (!topOnly)
11025             {
11026                 gtDispChild(tree->gtArrElem.gtArrObj, indentStack, IIArc, nullptr, topOnly);
11027
11028                 unsigned dim;
11029                 for (dim = 0; dim < tree->gtArrElem.gtArrRank; dim++)
11030                 {
11031                     IndentInfo arcType = ((dim + 1) == tree->gtArrElem.gtArrRank) ? IIArcBottom : IIArc;
11032                     gtDispChild(tree->gtArrElem.gtArrInds[dim], indentStack, arcType, nullptr, topOnly);
11033                 }
11034             }
11035             break;
11036
11037         case GT_ARR_OFFSET:
11038             gtDispVN(tree);
11039             printf("\n");
11040             if (!topOnly)
11041             {
11042                 gtDispChild(tree->gtArrOffs.gtOffset, indentStack, IIArc, nullptr, topOnly);
11043                 gtDispChild(tree->gtArrOffs.gtIndex, indentStack, IIArc, nullptr, topOnly);
11044                 gtDispChild(tree->gtArrOffs.gtArrObj, indentStack, IIArcBottom, nullptr, topOnly);
11045             }
11046             break;
11047
11048         case GT_CMPXCHG:
11049             gtDispVN(tree);
11050             printf("\n");
11051             if (!topOnly)
11052             {
11053                 gtDispChild(tree->gtCmpXchg.gtOpLocation, indentStack, IIArc, nullptr, topOnly);
11054                 gtDispChild(tree->gtCmpXchg.gtOpValue, indentStack, IIArc, nullptr, topOnly);
11055                 gtDispChild(tree->gtCmpXchg.gtOpComparand, indentStack, IIArcBottom, nullptr, topOnly);
11056             }
11057             break;
11058
11059         case GT_ARR_BOUNDS_CHECK:
11060 #ifdef FEATURE_SIMD
11061         case GT_SIMD_CHK:
11062 #endif // FEATURE_SIMD
11063 #ifdef FEATURE_HW_INTRINSICS
11064         case GT_HW_INTRINSIC_CHK:
11065 #endif // FEATURE_HW_INTRINSICS
11066             gtDispVN(tree);
11067             printf("\n");
11068             if (!topOnly)
11069             {
11070                 gtDispChild(tree->gtBoundsChk.gtIndex, indentStack, IIArc, nullptr, topOnly);
11071                 gtDispChild(tree->gtBoundsChk.gtArrLen, indentStack, IIArcBottom, nullptr, topOnly);
11072             }
11073             break;
11074
11075         case GT_STORE_DYN_BLK:
11076         case GT_DYN_BLK:
11077             if (tree->OperIsCopyBlkOp())
11078             {
11079                 printf(" (copy)");
11080             }
11081             else if (tree->OperIsInitBlkOp())
11082             {
11083                 printf(" (init)");
11084             }
11085             gtDispVN(tree);
11086             printf("\n");
11087             if (!topOnly)
11088             {
11089                 if (tree->gtDynBlk.Data() != nullptr)
11090                 {
11091                     gtDispChild(tree->gtDynBlk.Data(), indentStack, IIArc, nullptr, topOnly);
11092                 }
11093                 gtDispChild(tree->gtDynBlk.Addr(), indentStack, IIArc, nullptr, topOnly);
11094                 gtDispChild(tree->gtDynBlk.gtDynamicSize, indentStack, IIArcBottom, nullptr, topOnly);
11095             }
11096             break;
11097
11098         default:
11099             printf("<DON'T KNOW HOW TO DISPLAY THIS NODE> :");
11100             printf(""); // null string means flush
11101             break;
11102     }
11103 }
11104
11105 //------------------------------------------------------------------------
11106 // gtGetArgMsg: Construct a message about the given argument
11107 //
11108 // Arguments:
11109 //    call      - The call for which 'arg' is an argument
11110 //    arg       - The argument for which a message should be constructed
11111 //    argNum    - The ordinal number of the arg in the argument list
11112 //    listCount - When printing in LIR form this is the count for a GT_FIELD_LIST
11113 //                or -1 if we are not printing in LIR form
11114 //    bufp      - A pointer to the buffer into which the message is written
11115 //    bufLength - The length of the buffer pointed to by bufp
11116 //
11117 // Return Value:
11118 //    No return value, but bufp is written.
11119 //
11120 // Assumptions:
11121 //    'call' must be a call node
11122 //    'arg' must be an argument to 'call' (else gtArgEntryByNode will assert)
11123
11124 void Compiler::gtGetArgMsg(
11125     GenTreeCall* call, GenTree* arg, unsigned argNum, int listCount, char* bufp, unsigned bufLength)
11126 {
11127     if (call->gtCallLateArgs != nullptr)
11128     {
11129         fgArgTabEntry* curArgTabEntry = gtArgEntryByArgNum(call, argNum);
11130         assert(curArgTabEntry);
11131
11132         if (arg->gtFlags & GTF_LATE_ARG)
11133         {
11134             sprintf_s(bufp, bufLength, "arg%d SETUP%c", argNum, 0);
11135         }
11136         else
11137         {
11138 #ifdef _TARGET_ARM_
11139             if (curArgTabEntry->isSplit)
11140             {
11141                 regNumber firstReg = curArgTabEntry->regNum;
11142                 if (listCount == -1)
11143                 {
11144                     if (curArgTabEntry->numRegs == 1)
11145                     {
11146                         sprintf_s(bufp, bufLength, "arg%d %s out+%02x%c", argNum, compRegVarName(firstReg),
11147                                   (curArgTabEntry->slotNum) * TARGET_POINTER_SIZE, 0);
11148                     }
11149                     else
11150                     {
11151                         regNumber lastReg   = REG_STK;
11152                         char      separator = (curArgTabEntry->numRegs == 2) ? ',' : '-';
11153                         if (curArgTabEntry->isHfaRegArg)
11154                         {
11155                             unsigned lastRegNum = genMapFloatRegNumToRegArgNum(firstReg) + curArgTabEntry->numRegs - 1;
11156                             lastReg             = genMapFloatRegArgNumToRegNum(lastRegNum);
11157                         }
11158                         else
11159                         {
11160                             unsigned lastRegNum = genMapIntRegNumToRegArgNum(firstReg) + curArgTabEntry->numRegs - 1;
11161                             lastReg             = genMapIntRegArgNumToRegNum(lastRegNum);
11162                         }
11163                         sprintf_s(bufp, bufLength, "arg%d %s%c%s out+%02x%c", argNum, compRegVarName(firstReg),
11164                                   separator, compRegVarName(lastReg), (curArgTabEntry->slotNum) * TARGET_POINTER_SIZE,
11165                                   0);
11166                     }
11167                 }
11168                 else
11169                 {
11170                     unsigned curArgNum = BAD_VAR_NUM;
11171                     bool     isFloat   = curArgTabEntry->isHfaRegArg;
11172                     if (isFloat)
11173                     {
11174                         curArgNum = genMapFloatRegNumToRegArgNum(firstReg) + listCount;
11175                     }
11176                     else
11177                     {
11178                         curArgNum = genMapIntRegNumToRegArgNum(firstReg) + listCount;
11179                     }
11180
11181                     if (!isFloat && curArgNum < MAX_REG_ARG)
11182                     {
11183                         regNumber curReg = genMapIntRegArgNumToRegNum(curArgNum);
11184                         sprintf_s(bufp, bufLength, "arg%d m%d %s%c", argNum, listCount, compRegVarName(curReg), 0);
11185                     }
11186                     else if (isFloat && curArgNum < MAX_FLOAT_REG_ARG)
11187                     {
11188                         regNumber curReg = genMapFloatRegArgNumToRegNum(curArgNum);
11189                         sprintf_s(bufp, bufLength, "arg%d m%d %s%c", argNum, listCount, compRegVarName(curReg), 0);
11190                     }
11191                     else
11192                     {
11193                         unsigned stackSlot = listCount - curArgTabEntry->numRegs;
11194                         sprintf_s(bufp, bufLength, "arg%d m%d out+%02x%c", argNum, listCount,
11195                                   stackSlot * TARGET_POINTER_SIZE, 0);
11196                     }
11197                 }
11198                 return;
11199             }
11200 #endif // _TARGET_ARM_
11201 #if FEATURE_FIXED_OUT_ARGS
11202             if (listCount == -1)
11203             {
11204                 sprintf_s(bufp, bufLength, "arg%d out+%02x%c", argNum, curArgTabEntry->slotNum * TARGET_POINTER_SIZE,
11205                           0);
11206             }
11207             else // listCount is 0,1,2 or 3
11208             {
11209                 assert(listCount <= MAX_ARG_REG_COUNT);
11210                 sprintf_s(bufp, bufLength, "arg%d out+%02x%c", argNum,
11211                           (curArgTabEntry->slotNum + listCount) * TARGET_POINTER_SIZE, 0);
11212             }
11213 #else
11214             sprintf_s(bufp, bufLength, "arg%d on STK%c", argNum, 0);
11215 #endif
11216         }
11217     }
11218     else
11219     {
11220         sprintf_s(bufp, bufLength, "arg%d%c", argNum, 0);
11221     }
11222 }
11223
11224 //------------------------------------------------------------------------
11225 // gtGetLateArgMsg: Construct a message about the given argument
11226 //
11227 // Arguments:
11228 //    call         - The call for which 'arg' is an argument
11229 //    argx         - The argument for which a message should be constructed
11230 //    lateArgIndex - The ordinal number of the arg in the lastArg  list
11231 //    listCount    - When printing in LIR form this is the count for a multireg GT_FIELD_LIST
11232 //                   or -1 if we are not printing in LIR form
11233 //    bufp         - A pointer to the buffer into which the message is written
11234 //    bufLength    - The length of the buffer pointed to by bufp
11235 //
11236 // Return Value:
11237 //    No return value, but bufp is written.
11238 //
11239 // Assumptions:
11240 //    'call' must be a call node
11241 //    'arg' must be an argument to 'call' (else gtArgEntryByNode will assert)
11242
11243 void Compiler::gtGetLateArgMsg(
11244     GenTreeCall* call, GenTree* argx, int lateArgIndex, int listCount, char* bufp, unsigned bufLength)
11245 {
11246     assert(!argx->IsArgPlaceHolderNode()); // No place holders nodes are in gtCallLateArgs;
11247
11248     fgArgTabEntry* curArgTabEntry = gtArgEntryByLateArgIndex(call, lateArgIndex);
11249     assert(curArgTabEntry);
11250     regNumber argReg = curArgTabEntry->regNum;
11251
11252 #if !FEATURE_FIXED_OUT_ARGS
11253     assert(lateArgIndex < call->regArgListCount);
11254     assert(argReg == call->regArgList[lateArgIndex]);
11255 #else
11256     if (argReg == REG_STK)
11257     {
11258         sprintf_s(bufp, bufLength, "arg%d in out+%02x%c", curArgTabEntry->argNum,
11259                   curArgTabEntry->slotNum * TARGET_POINTER_SIZE, 0);
11260     }
11261     else
11262 #endif
11263     {
11264         if (gtArgIsThisPtr(curArgTabEntry))
11265         {
11266             sprintf_s(bufp, bufLength, "this in %s%c", compRegVarName(argReg), 0);
11267         }
11268 #ifdef _TARGET_ARM_
11269         else if (curArgTabEntry->isSplit)
11270         {
11271             regNumber firstReg = curArgTabEntry->regNum;
11272             unsigned  argNum   = curArgTabEntry->argNum;
11273             if (listCount == -1)
11274             {
11275                 if (curArgTabEntry->numRegs == 1)
11276                 {
11277                     sprintf_s(bufp, bufLength, "arg%d %s out+%02x%c", argNum, compRegVarName(firstReg),
11278                               (curArgTabEntry->slotNum) * TARGET_POINTER_SIZE, 0);
11279                 }
11280                 else
11281                 {
11282                     regNumber lastReg   = REG_STK;
11283                     char      separator = (curArgTabEntry->numRegs == 2) ? ',' : '-';
11284                     if (curArgTabEntry->isHfaRegArg)
11285                     {
11286                         unsigned lastRegNum = genMapFloatRegNumToRegArgNum(firstReg) + curArgTabEntry->numRegs - 1;
11287                         lastReg             = genMapFloatRegArgNumToRegNum(lastRegNum);
11288                     }
11289                     else
11290                     {
11291                         unsigned lastRegNum = genMapIntRegNumToRegArgNum(firstReg) + curArgTabEntry->numRegs - 1;
11292                         lastReg             = genMapIntRegArgNumToRegNum(lastRegNum);
11293                     }
11294                     sprintf_s(bufp, bufLength, "arg%d %s%c%s out+%02x%c", argNum, compRegVarName(firstReg), separator,
11295                               compRegVarName(lastReg), (curArgTabEntry->slotNum) * TARGET_POINTER_SIZE, 0);
11296                 }
11297             }
11298             else
11299             {
11300                 unsigned curArgNum = BAD_VAR_NUM;
11301                 bool     isFloat   = curArgTabEntry->isHfaRegArg;
11302                 if (isFloat)
11303                 {
11304                     curArgNum = genMapFloatRegNumToRegArgNum(firstReg) + listCount;
11305                 }
11306                 else
11307                 {
11308                     curArgNum = genMapIntRegNumToRegArgNum(firstReg) + listCount;
11309                 }
11310
11311                 if (!isFloat && curArgNum < MAX_REG_ARG)
11312                 {
11313                     regNumber curReg = genMapIntRegArgNumToRegNum(curArgNum);
11314                     sprintf_s(bufp, bufLength, "arg%d m%d %s%c", argNum, listCount, compRegVarName(curReg), 0);
11315                 }
11316                 else if (isFloat && curArgNum < MAX_FLOAT_REG_ARG)
11317                 {
11318                     regNumber curReg = genMapFloatRegArgNumToRegNum(curArgNum);
11319                     sprintf_s(bufp, bufLength, "arg%d m%d %s%c", argNum, listCount, compRegVarName(curReg), 0);
11320                 }
11321                 else
11322                 {
11323                     unsigned stackSlot = listCount - curArgTabEntry->numRegs;
11324                     sprintf_s(bufp, bufLength, "arg%d m%d out+%02x%c", argNum, listCount,
11325                               stackSlot * TARGET_POINTER_SIZE, 0);
11326                 }
11327             }
11328             return;
11329         }
11330 #endif // _TARGET_ARM_
11331         else
11332         {
11333 #if FEATURE_MULTIREG_ARGS
11334             if (curArgTabEntry->numRegs >= 2)
11335             {
11336                 // listCount could be -1 but it is signed, so this comparison is OK.
11337                 assert(listCount <= MAX_ARG_REG_COUNT);
11338                 char separator = (curArgTabEntry->numRegs == 2) ? ',' : '-';
11339                 sprintf_s(bufp, bufLength, "arg%d %s%c%s%c", curArgTabEntry->argNum, compRegVarName(argReg), separator,
11340                           compRegVarName(curArgTabEntry->getRegNum(curArgTabEntry->numRegs - 1)), 0);
11341             }
11342             else
11343 #endif
11344             {
11345                 sprintf_s(bufp, bufLength, "arg%d in %s%c", curArgTabEntry->argNum, compRegVarName(argReg), 0);
11346             }
11347         }
11348     }
11349 }
11350
11351 //------------------------------------------------------------------------
11352 // gtDispArgList: Dump the tree for a call arg list
11353 //
11354 // Arguments:
11355 //    call         - The call to dump arguments for
11356 //    indentStack  - the specification for the current level of indentation & arcs
11357 //
11358 // Return Value:
11359 //    None.
11360 //
11361 void Compiler::gtDispArgList(GenTreeCall* call, IndentStack* indentStack)
11362 {
11363     GenTree*  args      = call->gtCallArgs;
11364     unsigned  argnum    = 0;
11365     const int BufLength = 256;
11366     char      buf[BufLength];
11367     char*     bufp        = &buf[0];
11368     unsigned  numChildren = call->NumChildren();
11369     assert(numChildren != 0);
11370     bool argListIsLastChild = (args == call->GetChild(numChildren - 1));
11371
11372     IndentInfo arcType = IIArc;
11373     if (call->gtCallObjp != nullptr)
11374     {
11375         argnum++;
11376     }
11377
11378     while (args != nullptr)
11379     {
11380         assert(args->gtOper == GT_LIST);
11381         GenTree* arg = args->gtOp.gtOp1;
11382         if (!arg->IsNothingNode() && !arg->IsArgPlaceHolderNode())
11383         {
11384             gtGetArgMsg(call, arg, argnum, -1, bufp, BufLength);
11385             if (argListIsLastChild && (args->gtOp.gtOp2 == nullptr))
11386             {
11387                 arcType = IIArcBottom;
11388             }
11389             gtDispChild(arg, indentStack, arcType, bufp, false);
11390         }
11391         args = args->gtOp.gtOp2;
11392         argnum++;
11393     }
11394 }
11395
11396 //------------------------------------------------------------------------
11397 // gtDispArgList: Dump the tree for a call arg list
11398 //
11399 // Arguments:
11400 //    tree         - The call for which 'arg' is an argument
11401 //    indentStack  - the specification for the current level of indentation & arcs
11402 //
11403 // Return Value:
11404 //    None.
11405 //
11406 // Assumptions:
11407 //    'tree' must be a GT_LIST node
11408
11409 void Compiler::gtDispTreeList(GenTree* tree, IndentStack* indentStack /* = nullptr */)
11410 {
11411     for (/*--*/; tree != nullptr; tree = tree->gtNext)
11412     {
11413         gtDispTree(tree, indentStack);
11414         printf("\n");
11415     }
11416 }
11417
11418 //------------------------------------------------------------------------
11419 // Compiler::gtDispRange: dumps a range of LIR.
11420 //
11421 // Arguments:
11422 //    range - the range of LIR to display.
11423 //
11424 void Compiler::gtDispRange(LIR::ReadOnlyRange const& range)
11425 {
11426     for (GenTree* node : range)
11427     {
11428         gtDispLIRNode(node);
11429     }
11430 }
11431
11432 //------------------------------------------------------------------------
11433 // Compiler::gtDispTreeRange: dumps the LIR range that contains all of the
11434 //                            nodes in the dataflow tree rooted at a given
11435 //                            node.
11436 //
11437 // Arguments:
11438 //    containingRange - the LIR range that contains the root node.
11439 //    tree - the root of the dataflow tree.
11440 //
11441 void Compiler::gtDispTreeRange(LIR::Range& containingRange, GenTree* tree)
11442 {
11443     bool unused;
11444     gtDispRange(containingRange.GetTreeRange(tree, &unused));
11445 }
11446
11447 //------------------------------------------------------------------------
11448 // Compiler::gtDispLIRNode: dumps a single LIR node.
11449 //
11450 // Arguments:
11451 //    node - the LIR node to dump.
11452 //    prefixMsg - an optional prefix for each line of output.
11453 //
11454 void Compiler::gtDispLIRNode(GenTree* node, const char* prefixMsg /* = nullptr */)
11455 {
11456     auto displayOperand = [](GenTree* operand, const char* message, IndentInfo operandArc, IndentStack& indentStack,
11457                              size_t prefixIndent) {
11458         assert(operand != nullptr);
11459         assert(message != nullptr);
11460
11461         if (prefixIndent != 0)
11462         {
11463             printf("%*s", (int)prefixIndent, "");
11464         }
11465
11466         // 49 spaces for alignment
11467         printf("%-49s", "");
11468 #if FEATURE_SET_FLAGS
11469         // additional flag enlarges the flag field by one character
11470         printf(" ");
11471 #endif
11472
11473         indentStack.Push(operandArc);
11474         indentStack.print();
11475         indentStack.Pop();
11476         operandArc = IIArc;
11477
11478         printf("  t%-5d %-6s %s\n", operand->gtTreeID, varTypeName(operand->TypeGet()), message);
11479     };
11480
11481     IndentStack indentStack(this);
11482
11483     size_t prefixIndent = 0;
11484     if (prefixMsg != nullptr)
11485     {
11486         prefixIndent = strlen(prefixMsg);
11487     }
11488
11489     const int bufLength = 256;
11490     char      buf[bufLength];
11491
11492     const bool nodeIsCall = node->IsCall();
11493
11494     // Visit operands
11495     IndentInfo operandArc = IIArcTop;
11496     for (GenTree* operand : node->Operands())
11497     {
11498         if (operand->IsArgPlaceHolderNode() || !operand->IsValue())
11499         {
11500             // Either of these situations may happen with calls.
11501             continue;
11502         }
11503
11504         if (nodeIsCall)
11505         {
11506             GenTreeCall* call = node->AsCall();
11507             if (operand == call->gtCallObjp)
11508             {
11509                 sprintf_s(buf, sizeof(buf), "this in %s", compRegVarName(REG_ARG_0));
11510                 displayOperand(operand, buf, operandArc, indentStack, prefixIndent);
11511             }
11512             else if (operand == call->gtCallAddr)
11513             {
11514                 displayOperand(operand, "calli tgt", operandArc, indentStack, prefixIndent);
11515             }
11516             else if (operand == call->gtControlExpr)
11517             {
11518                 displayOperand(operand, "control expr", operandArc, indentStack, prefixIndent);
11519             }
11520             else if (operand == call->gtCallCookie)
11521             {
11522                 displayOperand(operand, "cookie", operandArc, indentStack, prefixIndent);
11523             }
11524             else
11525             {
11526                 fgArgTabEntry* curArgTabEntry = gtArgEntryByNode(call, operand);
11527                 assert(curArgTabEntry);
11528
11529                 if (operand->OperGet() == GT_LIST)
11530                 {
11531                     int listIndex = 0;
11532                     for (GenTreeArgList* element = operand->AsArgList(); element != nullptr; element = element->Rest())
11533                     {
11534                         operand = element->Current();
11535                         if (curArgTabEntry->lateArgInx == (unsigned)-1)
11536                         {
11537                             gtGetArgMsg(call, operand, curArgTabEntry->argNum, listIndex, buf, sizeof(buf));
11538                         }
11539                         else
11540                         {
11541                             gtGetLateArgMsg(call, operand, curArgTabEntry->lateArgInx, listIndex, buf, sizeof(buf));
11542                         }
11543
11544                         displayOperand(operand, buf, operandArc, indentStack, prefixIndent);
11545                         operandArc = IIArc;
11546                     }
11547                 }
11548                 else
11549                 {
11550                     if (!curArgTabEntry->isLateArg())
11551                     {
11552                         gtGetArgMsg(call, operand, curArgTabEntry->argNum, -1, buf, sizeof(buf));
11553                     }
11554                     else
11555                     {
11556                         gtGetLateArgMsg(call, operand, curArgTabEntry->lateArgInx, -1, buf, sizeof(buf));
11557                     }
11558
11559                     displayOperand(operand, buf, operandArc, indentStack, prefixIndent);
11560                 }
11561             }
11562         }
11563         else if (node->OperIsDynBlkOp())
11564         {
11565             if (operand == node->AsBlk()->Addr())
11566             {
11567                 displayOperand(operand, "lhs", operandArc, indentStack, prefixIndent);
11568             }
11569             else if (operand == node->AsBlk()->Data())
11570             {
11571                 displayOperand(operand, "rhs", operandArc, indentStack, prefixIndent);
11572             }
11573             else
11574             {
11575                 assert(operand == node->AsDynBlk()->gtDynamicSize);
11576                 displayOperand(operand, "size", operandArc, indentStack, prefixIndent);
11577             }
11578         }
11579         else if (node->OperGet() == GT_DYN_BLK)
11580         {
11581             if (operand == node->AsBlk()->Addr())
11582             {
11583                 displayOperand(operand, "lhs", operandArc, indentStack, prefixIndent);
11584             }
11585             else
11586             {
11587                 assert(operand == node->AsDynBlk()->gtDynamicSize);
11588                 displayOperand(operand, "size", operandArc, indentStack, prefixIndent);
11589             }
11590         }
11591         else if (node->OperIs(GT_ASG))
11592         {
11593             if (operand == node->gtGetOp1())
11594             {
11595                 displayOperand(operand, "lhs", operandArc, indentStack, prefixIndent);
11596             }
11597             else
11598             {
11599                 displayOperand(operand, "rhs", operandArc, indentStack, prefixIndent);
11600             }
11601         }
11602         else
11603         {
11604             displayOperand(operand, "", operandArc, indentStack, prefixIndent);
11605         }
11606
11607         operandArc = IIArc;
11608     }
11609
11610     // Visit the operator
11611
11612     if (prefixMsg != nullptr)
11613     {
11614         printf("%s", prefixMsg);
11615     }
11616
11617     const bool topOnly = true;
11618     const bool isLIR   = true;
11619     gtDispTree(node, &indentStack, nullptr, topOnly, isLIR);
11620 }
11621
11622 /*****************************************************************************/
11623 #endif // DEBUG
11624
11625 /*****************************************************************************
11626  *
11627  *  Check if the given node can be folded,
11628  *  and call the methods to perform the folding
11629  */
11630
11631 GenTree* Compiler::gtFoldExpr(GenTree* tree)
11632 {
11633     unsigned kind = tree->OperKind();
11634
11635     /* We must have a simple operation to fold */
11636
11637     // If we're in CSE, it's not safe to perform tree
11638     // folding given that it can will potentially
11639     // change considered CSE candidates.
11640     if (optValnumCSE_phase)
11641     {
11642         return tree;
11643     }
11644
11645     if (!(kind & GTK_SMPOP))
11646     {
11647         return tree;
11648     }
11649
11650     GenTree* op1 = tree->gtOp.gtOp1;
11651
11652     /* Filter out non-foldable trees that can have constant children */
11653
11654     assert(kind & (GTK_UNOP | GTK_BINOP));
11655     switch (tree->gtOper)
11656     {
11657         case GT_RETFILT:
11658         case GT_RETURN:
11659         case GT_IND:
11660             return tree;
11661         default:
11662             break;
11663     }
11664
11665     /* try to fold the current node */
11666
11667     if ((kind & GTK_UNOP) && op1)
11668     {
11669         if (op1->OperKind() & GTK_CONST)
11670         {
11671             return gtFoldExprConst(tree);
11672         }
11673     }
11674     else if ((kind & GTK_BINOP) && op1 && tree->gtOp.gtOp2 &&
11675              // Don't take out conditionals for debugging
11676              !((opts.compDbgCode || opts.MinOpts()) && tree->OperIsCompare()))
11677     {
11678         GenTree* op2 = tree->gtOp.gtOp2;
11679
11680         // The atomic operations are exempted here because they are never computable statically;
11681         // one of their arguments is an address.
11682         if (((op1->OperKind() & op2->OperKind()) & GTK_CONST) && !tree->OperIsAtomicOp())
11683         {
11684             /* both nodes are constants - fold the expression */
11685             return gtFoldExprConst(tree);
11686         }
11687         else if ((op1->OperKind() | op2->OperKind()) & GTK_CONST)
11688         {
11689             /* at least one is a constant - see if we have a
11690              * special operator that can use only one constant
11691              * to fold - e.g. booleans */
11692
11693             return gtFoldExprSpecial(tree);
11694         }
11695         else if (tree->OperIsCompare())
11696         {
11697             /* comparisons of two local variables can sometimes be folded */
11698
11699             return gtFoldExprCompare(tree);
11700         }
11701         else if (op2->OperGet() == GT_COLON)
11702         {
11703             assert(tree->OperGet() == GT_QMARK);
11704
11705             GenTree* colon_op1 = op2->gtOp.gtOp1;
11706             GenTree* colon_op2 = op2->gtOp.gtOp2;
11707
11708             if (gtCompareTree(colon_op1, colon_op2))
11709             {
11710                 // Both sides of the GT_COLON are the same tree
11711
11712                 GenTree* sideEffList = nullptr;
11713                 gtExtractSideEffList(op1, &sideEffList);
11714
11715                 // Clear colon flags only if the qmark itself is not conditionaly executed
11716                 if ((tree->gtFlags & GTF_COLON_COND) == 0)
11717                 {
11718                     fgWalkTreePre(&colon_op2, gtClearColonCond);
11719                 }
11720
11721                 if (sideEffList == nullptr)
11722                 {
11723                     // No side-effects, just return colon_op2
11724                     return colon_op2;
11725                 }
11726                 else
11727                 {
11728 #ifdef DEBUG
11729                     if (verbose)
11730                     {
11731                         printf("\nIdentical GT_COLON trees with side effects! Extracting side effects...\n");
11732                         gtDispTree(sideEffList);
11733                         printf("\n");
11734                     }
11735 #endif
11736                     // Change the GT_COLON into a GT_COMMA node with the side-effects
11737                     op2->ChangeOper(GT_COMMA);
11738                     op2->gtFlags |= (sideEffList->gtFlags & GTF_ALL_EFFECT);
11739                     op2->gtOp.gtOp1 = sideEffList;
11740                     return op2;
11741                 }
11742             }
11743         }
11744     }
11745
11746     /* Return the original node (folded/bashed or not) */
11747
11748     return tree;
11749 }
11750
11751 //------------------------------------------------------------------------
11752 // gtFoldExprCall: see if a call is foldable
11753 //
11754 // Arguments:
11755 //    call - call to examine
11756 //
11757 // Returns:
11758 //    The original call if no folding happened.
11759 //    An alternative tree if folding happens.
11760 //
11761 // Notes:
11762 //    Checks for calls to Type.op_Equality, Type.op_Inequality, and
11763 //    Enum.HasFlag, and if the call is to one of these,
11764 //    attempts to optimize.
11765
11766 GenTree* Compiler::gtFoldExprCall(GenTreeCall* call)
11767 {
11768     // Can only fold calls to special intrinsics.
11769     if ((call->gtCallMoreFlags & GTF_CALL_M_SPECIAL_INTRINSIC) == 0)
11770     {
11771         return call;
11772     }
11773
11774     // Defer folding if not optimizing.
11775     if (opts.compDbgCode || opts.MinOpts())
11776     {
11777         return call;
11778     }
11779
11780     // Fetch id of the intrinsic.
11781     const CorInfoIntrinsics methodID = info.compCompHnd->getIntrinsicID(call->gtCallMethHnd);
11782
11783     switch (methodID)
11784     {
11785         case CORINFO_INTRINSIC_TypeEQ:
11786         case CORINFO_INTRINSIC_TypeNEQ:
11787         {
11788             noway_assert(call->TypeGet() == TYP_INT);
11789             GenTree* op1 = call->gtCallArgs->gtOp.gtOp1;
11790             GenTree* op2 = call->gtCallArgs->gtOp.gtOp2->gtOp.gtOp1;
11791
11792             // If either operand is known to be a RuntimeType, this can be folded
11793             GenTree* result = gtFoldTypeEqualityCall(methodID, op1, op2);
11794             if (result != nullptr)
11795             {
11796                 return result;
11797             }
11798             break;
11799         }
11800
11801         default:
11802             break;
11803     }
11804
11805     // Check for a new-style jit intrinsic.
11806     const NamedIntrinsic ni = lookupNamedIntrinsic(call->gtCallMethHnd);
11807
11808     if (ni == NI_System_Enum_HasFlag)
11809     {
11810         GenTree* thisOp = call->gtCallObjp;
11811         GenTree* flagOp = call->gtCallArgs->gtOp.gtOp1;
11812         GenTree* result = gtOptimizeEnumHasFlag(thisOp, flagOp);
11813
11814         if (result != nullptr)
11815         {
11816             return result;
11817         }
11818     }
11819
11820     return call;
11821 }
11822
11823 //------------------------------------------------------------------------
11824 // gtFoldTypeEqualityCall: see if a (potential) type equality call is foldable
11825 //
11826 // Arguments:
11827 //    methodID -- type equality intrinsic ID
11828 //    op1 -- first argument to call
11829 //    op2 -- second argument to call
11830 //
11831 // Returns:
11832 //    nulltpr if no folding happened.
11833 //    An alternative tree if folding happens.
11834 //
11835 // Notes:
11836 //    If either operand is known to be a a RuntimeType, then the type
11837 //    equality methods will simply check object identity and so we can
11838 //    fold the call into a simple compare of the call's operands.
11839
11840 GenTree* Compiler::gtFoldTypeEqualityCall(CorInfoIntrinsics methodID, GenTree* op1, GenTree* op2)
11841 {
11842     // The method must be be a type equality intrinsic
11843     assert(methodID == CORINFO_INTRINSIC_TypeEQ || methodID == CORINFO_INTRINSIC_TypeNEQ);
11844
11845     if ((gtGetTypeProducerKind(op1) == TPK_Unknown) && (gtGetTypeProducerKind(op2) == TPK_Unknown))
11846     {
11847         return nullptr;
11848     }
11849
11850     const genTreeOps simpleOp = (methodID == CORINFO_INTRINSIC_TypeEQ) ? GT_EQ : GT_NE;
11851
11852     JITDUMP("\nFolding call to Type:op_%s to a simple compare via %s\n",
11853             methodID == CORINFO_INTRINSIC_TypeEQ ? "Equality" : "Inequality", GenTree::OpName(simpleOp));
11854
11855     GenTree* compare = gtNewOperNode(simpleOp, TYP_INT, op1, op2);
11856
11857     return compare;
11858 }
11859
11860 /*****************************************************************************
11861  *
11862  *  Some comparisons can be folded:
11863  *
11864  *    locA        == locA
11865  *    classVarA   == classVarA
11866  *    locA + locB == locB + locA
11867  *
11868  */
11869
11870 GenTree* Compiler::gtFoldExprCompare(GenTree* tree)
11871 {
11872     GenTree* op1 = tree->gtOp.gtOp1;
11873     GenTree* op2 = tree->gtOp.gtOp2;
11874
11875     assert(tree->OperIsCompare());
11876
11877     /* Filter out cases that cannot be folded here */
11878
11879     /* Do not fold floats or doubles (e.g. NaN != Nan) */
11880
11881     if (varTypeIsFloating(op1->TypeGet()))
11882     {
11883         return tree;
11884     }
11885
11886     /* Currently we can only fold when the two subtrees exactly match */
11887
11888     if ((tree->gtFlags & GTF_SIDE_EFFECT) || GenTree::Compare(op1, op2, true) == false)
11889     {
11890         return tree; /* return unfolded tree */
11891     }
11892
11893     GenTree* cons;
11894
11895     switch (tree->gtOper)
11896     {
11897         case GT_EQ:
11898         case GT_LE:
11899         case GT_GE:
11900             cons = gtNewIconNode(true); /* Folds to GT_CNS_INT(true) */
11901             break;
11902
11903         case GT_NE:
11904         case GT_LT:
11905         case GT_GT:
11906             cons = gtNewIconNode(false); /* Folds to GT_CNS_INT(false) */
11907             break;
11908
11909         default:
11910             assert(!"Unexpected relOp");
11911             return tree;
11912     }
11913
11914     /* The node has beeen folded into 'cons' */
11915
11916     if (fgGlobalMorph)
11917     {
11918         fgMorphTreeDone(cons);
11919     }
11920     else
11921     {
11922         cons->gtNext = tree->gtNext;
11923         cons->gtPrev = tree->gtPrev;
11924     }
11925
11926     return cons;
11927 }
11928
11929 //------------------------------------------------------------------------
11930 // gtCreateHandleCompare: generate a type handle comparison
11931 //
11932 // Arguments:
11933 //    oper -- comparison operation (equal/not equal)
11934 //    op1 -- first operand
11935 //    op2 -- second operand
11936 //    typeCheckInliningResult -- indicates how the comparison should happen
11937 //
11938 // Returns:
11939 //    Type comparison tree
11940 //
11941
11942 GenTree* Compiler::gtCreateHandleCompare(genTreeOps             oper,
11943                                          GenTree*               op1,
11944                                          GenTree*               op2,
11945                                          CorInfoInlineTypeCheck typeCheckInliningResult)
11946 {
11947     // If we can compare pointers directly, just emit the binary operation
11948     if (typeCheckInliningResult == CORINFO_INLINE_TYPECHECK_PASS)
11949     {
11950         return gtNewOperNode(oper, TYP_INT, op1, op2);
11951     }
11952
11953     assert(typeCheckInliningResult == CORINFO_INLINE_TYPECHECK_USE_HELPER);
11954
11955     // Emit a call to a runtime helper
11956     GenTreeArgList* helperArgs = gtNewArgList(op1, op2);
11957     GenTree*        ret        = gtNewHelperCallNode(CORINFO_HELP_ARE_TYPES_EQUIVALENT, TYP_INT, helperArgs);
11958     if (oper == GT_EQ)
11959     {
11960         ret = gtNewOperNode(GT_NE, TYP_INT, ret, gtNewIconNode(0, TYP_INT));
11961     }
11962     else
11963     {
11964         assert(oper == GT_NE);
11965         ret = gtNewOperNode(GT_EQ, TYP_INT, ret, gtNewIconNode(0, TYP_INT));
11966     }
11967
11968     return ret;
11969 }
11970
11971 //------------------------------------------------------------------------
11972 // gtFoldTypeCompare: see if a type comparison can be further simplified
11973 //
11974 // Arguments:
11975 //    tree -- tree possibly comparing types
11976 //
11977 // Returns:
11978 //    An alternative tree if folding happens.
11979 //    Original tree otherwise.
11980 //
11981 // Notes:
11982 //    Checks for
11983 //        typeof(...) == obj.GetType()
11984 //        typeof(...) == typeof(...)
11985 //
11986 //    And potentially optimizes away the need to obtain actual
11987 //    RuntimeType objects to do the comparison.
11988
11989 GenTree* Compiler::gtFoldTypeCompare(GenTree* tree)
11990 {
11991     // Only handle EQ and NE
11992     // (maybe relop vs null someday)
11993     const genTreeOps oper = tree->OperGet();
11994     if ((oper != GT_EQ) && (oper != GT_NE))
11995     {
11996         return tree;
11997     }
11998
11999     // Screen for the right kinds of operands
12000     GenTree* const         op1     = tree->gtOp.gtOp1;
12001     const TypeProducerKind op1Kind = gtGetTypeProducerKind(op1);
12002     if (op1Kind == TPK_Unknown)
12003     {
12004         return tree;
12005     }
12006
12007     GenTree* const         op2     = tree->gtOp.gtOp2;
12008     const TypeProducerKind op2Kind = gtGetTypeProducerKind(op2);
12009     if (op2Kind == TPK_Unknown)
12010     {
12011         return tree;
12012     }
12013
12014     // We must have a handle on one side or the other here to optimize,
12015     // otherwise we can't be sure that optimizing is sound.
12016     const bool op1IsFromHandle = (op1Kind == TPK_Handle);
12017     const bool op2IsFromHandle = (op2Kind == TPK_Handle);
12018
12019     if (!(op1IsFromHandle || op2IsFromHandle))
12020     {
12021         return tree;
12022     }
12023
12024     // If both types are created via handles, we can simply compare
12025     // handles (or the indirection cells for handles) instead of the
12026     // types that they'd create.
12027     if (op1IsFromHandle && op2IsFromHandle)
12028     {
12029         JITDUMP("Optimizing compare of types-from-handles to instead compare handles\n");
12030         GenTree*             op1ClassFromHandle = tree->gtOp.gtOp1->gtCall.gtCallArgs->gtOp.gtOp1;
12031         GenTree*             op2ClassFromHandle = tree->gtOp.gtOp2->gtCall.gtCallArgs->gtOp.gtOp1;
12032         GenTree*             op1TunneledHandle  = nullptr;
12033         GenTree*             op2TunneledHandle  = nullptr;
12034         CORINFO_CLASS_HANDLE cls1Hnd            = NO_CLASS_HANDLE;
12035         CORINFO_CLASS_HANDLE cls2Hnd            = NO_CLASS_HANDLE;
12036         unsigned             runtimeLookupCount = 0;
12037
12038         // Try and find class handles from op1 and op2
12039         cls1Hnd = gtGetHelperArgClassHandle(op1ClassFromHandle, &runtimeLookupCount, &op1TunneledHandle);
12040         cls2Hnd = gtGetHelperArgClassHandle(op2ClassFromHandle, &runtimeLookupCount, &op2TunneledHandle);
12041
12042         // If we have both class handles, try and resolve the type equality test completely.
12043         bool resolveFailed = false;
12044
12045         if ((cls1Hnd != NO_CLASS_HANDLE) && (cls2Hnd != NO_CLASS_HANDLE))
12046         {
12047             JITDUMP("Asking runtime to compare %p (%s) and %p (%s) for equality\n", dspPtr(cls1Hnd),
12048                     info.compCompHnd->getClassName(cls1Hnd), dspPtr(cls2Hnd), info.compCompHnd->getClassName(cls2Hnd));
12049             TypeCompareState s = info.compCompHnd->compareTypesForEquality(cls1Hnd, cls2Hnd);
12050
12051             if (s != TypeCompareState::May)
12052             {
12053                 // Type comparison result is known.
12054                 const bool typesAreEqual = (s == TypeCompareState::Must);
12055                 const bool operatorIsEQ  = (oper == GT_EQ);
12056                 const int  compareResult = operatorIsEQ ^ typesAreEqual ? 0 : 1;
12057                 JITDUMP("Runtime reports comparison is known at jit time: %u\n", compareResult);
12058                 GenTree* result = gtNewIconNode(compareResult);
12059
12060                 // Any runtime lookups that fed into this compare are
12061                 // now dead code, so they no longer require the runtime context.
12062                 assert(lvaGenericsContextUseCount >= runtimeLookupCount);
12063                 lvaGenericsContextUseCount -= runtimeLookupCount;
12064                 return result;
12065             }
12066             else
12067             {
12068                 resolveFailed = true;
12069             }
12070         }
12071
12072         if (resolveFailed)
12073         {
12074             JITDUMP("Runtime reports comparison is NOT known at jit time\n");
12075         }
12076         else
12077         {
12078             JITDUMP("Could not find handle for %s%s\n", (cls1Hnd == NO_CLASS_HANDLE) ? " cls1" : "",
12079                     (cls2Hnd == NO_CLASS_HANDLE) ? " cls2" : "");
12080         }
12081
12082         // We can't answer the equality comparison definitively at jit
12083         // time, but can still simplfy the comparison.
12084         //
12085         // Find out how we can compare the two handles.
12086         // NOTE: We're potentially passing NO_CLASS_HANDLE, but the runtime knows what to do with it here.
12087         CorInfoInlineTypeCheck inliningKind =
12088             info.compCompHnd->canInlineTypeCheck(cls1Hnd, CORINFO_INLINE_TYPECHECK_SOURCE_TOKEN);
12089
12090         // If the first type needs helper, check the other type: it might be okay with a simple compare.
12091         if (inliningKind == CORINFO_INLINE_TYPECHECK_USE_HELPER)
12092         {
12093             inliningKind = info.compCompHnd->canInlineTypeCheck(cls2Hnd, CORINFO_INLINE_TYPECHECK_SOURCE_TOKEN);
12094         }
12095
12096         assert(inliningKind == CORINFO_INLINE_TYPECHECK_PASS || inliningKind == CORINFO_INLINE_TYPECHECK_USE_HELPER);
12097
12098         // If we successfully tunneled through both operands, compare
12099         // the tunneled values, otherwise compare the original values.
12100         GenTree* compare;
12101         if ((op1TunneledHandle != nullptr) && (op2TunneledHandle != nullptr))
12102         {
12103             compare = gtCreateHandleCompare(oper, op1TunneledHandle, op2TunneledHandle, inliningKind);
12104         }
12105         else
12106         {
12107             compare = gtCreateHandleCompare(oper, op1ClassFromHandle, op2ClassFromHandle, inliningKind);
12108         }
12109
12110         // Drop any now-irrelvant flags
12111         compare->gtFlags |= tree->gtFlags & (GTF_RELOP_JMP_USED | GTF_RELOP_QMARK | GTF_DONT_CSE);
12112
12113         return compare;
12114     }
12115
12116     // Just one operand creates a type from a handle.
12117     //
12118     // If the other operand is fetching the type from an object,
12119     // we can sometimes optimize the type compare into a simpler
12120     // method table comparison.
12121     //
12122     // TODO: if other operand is null...
12123     if ((op1Kind != TPK_GetType) && (op2Kind != TPK_GetType))
12124     {
12125         return tree;
12126     }
12127
12128     GenTree* const opHandle = op1IsFromHandle ? op1 : op2;
12129     GenTree* const opOther  = op1IsFromHandle ? op2 : op1;
12130
12131     // Tunnel through the handle operand to get at the class handle involved.
12132     GenTree* const       opHandleArgument = opHandle->gtCall.gtCallArgs->gtOp.gtOp1;
12133     CORINFO_CLASS_HANDLE clsHnd           = gtGetHelperArgClassHandle(opHandleArgument);
12134
12135     // If we couldn't find the class handle, give up.
12136     if (clsHnd == NO_CLASS_HANDLE)
12137     {
12138         return tree;
12139     }
12140
12141     // Ask the VM if this type can be equality tested by a simple method
12142     // table comparison.
12143     CorInfoInlineTypeCheck typeCheckInliningResult =
12144         info.compCompHnd->canInlineTypeCheck(clsHnd, CORINFO_INLINE_TYPECHECK_SOURCE_VTABLE);
12145     if (typeCheckInliningResult == CORINFO_INLINE_TYPECHECK_NONE)
12146     {
12147         return tree;
12148     }
12149
12150     // We're good to go.
12151     JITDUMP("Optimizing compare of obj.GetType()"
12152             " and type-from-handle to compare method table pointer\n");
12153
12154     // opHandleArgument is the method table we're looking for.
12155     GenTree* const knownMT = opHandleArgument;
12156
12157     // Fetch object method table from the object itself.
12158     GenTree* objOp = nullptr;
12159
12160     // Note we may see intrinsified or regular calls to GetType
12161     if (opOther->OperGet() == GT_INTRINSIC)
12162     {
12163         objOp = opOther->gtUnOp.gtOp1;
12164     }
12165     else
12166     {
12167         assert(opOther->OperGet() == GT_CALL);
12168         objOp = opOther->gtCall.gtCallObjp;
12169     }
12170
12171     GenTree* const objMT = gtNewOperNode(GT_IND, TYP_I_IMPL, objOp);
12172
12173     // Update various flags
12174     objMT->gtFlags |= GTF_EXCEPT;
12175     compCurBB->bbFlags |= BBF_HAS_VTABREF;
12176     optMethodFlags |= OMF_HAS_VTABLEREF;
12177
12178     // Compare the two method tables
12179     GenTree* const compare = gtCreateHandleCompare(oper, objMT, knownMT, typeCheckInliningResult);
12180
12181     // Drop any now irrelevant flags
12182     compare->gtFlags |= tree->gtFlags & (GTF_RELOP_JMP_USED | GTF_RELOP_QMARK | GTF_DONT_CSE);
12183
12184     // And we're done
12185     return compare;
12186 }
12187
12188 //------------------------------------------------------------------------
12189 // gtGetHelperArgClassHandle: find the compile time class handle from
12190 //   a helper call argument tree
12191 //
12192 // Arguments:
12193 //    tree - tree that passes the handle to the helper
12194 //    runtimeLookupCount [optional, in/out] - incremented if tree was a runtime lookup
12195 //    handleTree [optional, out] - set to the literal operand tree for indirect handles
12196 //
12197 // Returns:
12198 //    The compile time class handle if known.
12199 //
12200 CORINFO_CLASS_HANDLE Compiler::gtGetHelperArgClassHandle(GenTree*  tree,
12201                                                          unsigned* runtimeLookupCount,
12202                                                          GenTree** handleTree)
12203 {
12204     CORINFO_CLASS_HANDLE result = NO_CLASS_HANDLE;
12205
12206     // Walk through any wrapping nop.
12207     if ((tree->gtOper == GT_NOP) && (tree->gtType == TYP_I_IMPL))
12208     {
12209         tree = tree->gtOp.gtOp1;
12210     }
12211
12212     // The handle could be a literal constant
12213     if ((tree->OperGet() == GT_CNS_INT) && (tree->TypeGet() == TYP_I_IMPL))
12214     {
12215         assert(tree->IsIconHandle(GTF_ICON_CLASS_HDL));
12216         result = (CORINFO_CLASS_HANDLE)tree->gtIntCon.gtCompileTimeHandle;
12217     }
12218     // Or the result of a runtime lookup
12219     else if (tree->OperGet() == GT_RUNTIMELOOKUP)
12220     {
12221         result = tree->AsRuntimeLookup()->GetClassHandle();
12222
12223         if (runtimeLookupCount != nullptr)
12224         {
12225             *runtimeLookupCount = *runtimeLookupCount + 1;
12226         }
12227     }
12228     // Or something reached indirectly
12229     else if (tree->gtOper == GT_IND)
12230     {
12231         // The handle indirs we are looking for will be marked as non-faulting.
12232         // Certain others (eg from refanytype) may not be.
12233         if (tree->gtFlags & GTF_IND_NONFAULTING)
12234         {
12235             GenTree* handleTreeInternal = tree->gtOp.gtOp1;
12236
12237             if ((handleTreeInternal->OperGet() == GT_CNS_INT) && (handleTreeInternal->TypeGet() == TYP_I_IMPL))
12238             {
12239                 // These handle constants should be class handles.
12240                 assert(handleTreeInternal->IsIconHandle(GTF_ICON_CLASS_HDL));
12241                 result = (CORINFO_CLASS_HANDLE)handleTreeInternal->gtIntCon.gtCompileTimeHandle;
12242
12243                 if (handleTree != nullptr)
12244                 {
12245                     *handleTree = handleTreeInternal;
12246                 }
12247             }
12248         }
12249     }
12250
12251     return result;
12252 }
12253
12254 /*****************************************************************************
12255  *
12256  *  Some binary operators can be folded even if they have only one
12257  *  operand constant - e.g. boolean operators, add with 0
12258  *  multiply with 1, etc
12259  */
12260
12261 GenTree* Compiler::gtFoldExprSpecial(GenTree* tree)
12262 {
12263     GenTree*   op1  = tree->gtOp.gtOp1;
12264     GenTree*   op2  = tree->gtOp.gtOp2;
12265     genTreeOps oper = tree->OperGet();
12266
12267     GenTree* op;
12268     GenTree* cons;
12269     ssize_t  val;
12270
12271     assert(tree->OperKind() & GTK_BINOP);
12272
12273     /* Filter out operators that cannot be folded here */
12274     if (oper == GT_CAST)
12275     {
12276         return tree;
12277     }
12278
12279     /* We only consider TYP_INT for folding
12280      * Do not fold pointer arithmetic (e.g. addressing modes!) */
12281
12282     if (oper != GT_QMARK && !varTypeIsIntOrI(tree->gtType))
12283     {
12284         return tree;
12285     }
12286
12287     /* Find out which is the constant node */
12288
12289     if (op1->IsCnsIntOrI())
12290     {
12291         op   = op2;
12292         cons = op1;
12293     }
12294     else if (op2->IsCnsIntOrI())
12295     {
12296         op   = op1;
12297         cons = op2;
12298     }
12299     else
12300     {
12301         return tree;
12302     }
12303
12304     /* Get the constant value */
12305
12306     val = cons->gtIntConCommon.IconValue();
12307
12308     /* Here op is the non-constant operand, val is the constant,
12309        first is true if the constant is op1 */
12310
12311     switch (oper)
12312     {
12313         case GT_EQ:
12314         case GT_NE:
12315         case GT_GT:
12316
12317             // Optimize boxed value classes; these are always false.  This IL is
12318             // generated when a generic value is tested against null:
12319             //     <T> ... foo(T x) { ... if ((object)x == null) ...
12320             if (val == 0 && op->IsBoxedValue())
12321             {
12322                 JITDUMP("\nAttempting to optimize BOX(valueType) %s null [%06u]\n", GenTree::OpName(oper),
12323                         dspTreeID(tree));
12324
12325                 // We don't expect GT_GT with signed compares, and we
12326                 // can't predict the result if we do see it, since the
12327                 // boxed object addr could have its high bit set.
12328                 if ((oper == GT_GT) && !tree->IsUnsigned())
12329                 {
12330                     JITDUMP(" bailing; unexpected signed compare via GT_GT\n");
12331                 }
12332                 else
12333                 {
12334                     // The tree under the box must be side effect free
12335                     // since we will drop it if we optimize.
12336                     assert(!gtTreeHasSideEffects(op->gtBox.gtOp.gtOp1, GTF_SIDE_EFFECT));
12337
12338                     // See if we can optimize away the box and related statements.
12339                     GenTree* boxSourceTree = gtTryRemoveBoxUpstreamEffects(op);
12340                     bool     didOptimize   = (boxSourceTree != nullptr);
12341
12342                     // If optimization succeeded, remove the box.
12343                     if (didOptimize)
12344                     {
12345                         // Set up the result of the compare.
12346                         int compareResult = 0;
12347                         if (oper == GT_GT)
12348                         {
12349                             // GT_GT(null, box) == false
12350                             // GT_GT(box, null) == true
12351                             compareResult = (op1 == op);
12352                         }
12353                         else if (oper == GT_EQ)
12354                         {
12355                             // GT_EQ(box, null) == false
12356                             // GT_EQ(null, box) == false
12357                             compareResult = 0;
12358                         }
12359                         else
12360                         {
12361                             assert(oper == GT_NE);
12362                             // GT_NE(box, null) == true
12363                             // GT_NE(null, box) == true
12364                             compareResult = 1;
12365                         }
12366
12367                         JITDUMP("\nSuccess: replacing BOX(valueType) %s null with %d\n", GenTree::OpName(oper),
12368                                 compareResult);
12369
12370                         op = gtNewIconNode(compareResult);
12371
12372                         if (fgGlobalMorph)
12373                         {
12374                             fgMorphTreeDone(op);
12375                         }
12376                         else
12377                         {
12378                             op->gtNext = tree->gtNext;
12379                             op->gtPrev = tree->gtPrev;
12380                         }
12381
12382                         return op;
12383                     }
12384                 }
12385             }
12386
12387             break;
12388
12389         case GT_ADD:
12390             if (val == 0)
12391             {
12392                 goto DONE_FOLD;
12393             }
12394             break;
12395
12396         case GT_MUL:
12397             if (val == 1)
12398             {
12399                 goto DONE_FOLD;
12400             }
12401             else if (val == 0)
12402             {
12403                 /* Multiply by zero - return the 'zero' node, but not if side effects */
12404                 if (!(op->gtFlags & GTF_SIDE_EFFECT))
12405                 {
12406                     op = cons;
12407                     goto DONE_FOLD;
12408                 }
12409             }
12410             break;
12411
12412         case GT_DIV:
12413         case GT_UDIV:
12414             if ((op2 == cons) && (val == 1) && !(op1->OperKind() & GTK_CONST))
12415             {
12416                 goto DONE_FOLD;
12417             }
12418             break;
12419
12420         case GT_SUB:
12421             if ((op2 == cons) && (val == 0) && !(op1->OperKind() & GTK_CONST))
12422             {
12423                 goto DONE_FOLD;
12424             }
12425             break;
12426
12427         case GT_AND:
12428             if (val == 0)
12429             {
12430                 /* AND with zero - return the 'zero' node, but not if side effects */
12431
12432                 if (!(op->gtFlags & GTF_SIDE_EFFECT))
12433                 {
12434                     op = cons;
12435                     goto DONE_FOLD;
12436                 }
12437             }
12438             else
12439             {
12440                 /* The GTF_BOOLEAN flag is set for nodes that are part
12441                  * of a boolean expression, thus all their children
12442                  * are known to evaluate to only 0 or 1 */
12443
12444                 if (tree->gtFlags & GTF_BOOLEAN)
12445                 {
12446
12447                     /* The constant value must be 1
12448                      * AND with 1 stays the same */
12449                     assert(val == 1);
12450                     goto DONE_FOLD;
12451                 }
12452             }
12453             break;
12454
12455         case GT_OR:
12456             if (val == 0)
12457             {
12458                 goto DONE_FOLD;
12459             }
12460             else if (tree->gtFlags & GTF_BOOLEAN)
12461             {
12462                 /* The constant value must be 1 - OR with 1 is 1 */
12463
12464                 assert(val == 1);
12465
12466                 /* OR with one - return the 'one' node, but not if side effects */
12467
12468                 if (!(op->gtFlags & GTF_SIDE_EFFECT))
12469                 {
12470                     op = cons;
12471                     goto DONE_FOLD;
12472                 }
12473             }
12474             break;
12475
12476         case GT_LSH:
12477         case GT_RSH:
12478         case GT_RSZ:
12479         case GT_ROL:
12480         case GT_ROR:
12481             if (val == 0)
12482             {
12483                 if (op2 == cons)
12484                 {
12485                     goto DONE_FOLD;
12486                 }
12487                 else if (!(op->gtFlags & GTF_SIDE_EFFECT))
12488                 {
12489                     op = cons;
12490                     goto DONE_FOLD;
12491                 }
12492             }
12493             break;
12494
12495         case GT_QMARK:
12496         {
12497             assert(op1 == cons && op2 == op && op2->gtOper == GT_COLON);
12498             assert(op2->gtOp.gtOp1 && op2->gtOp.gtOp2);
12499
12500             assert(val == 0 || val == 1);
12501
12502             GenTree* opToDelete;
12503             if (val)
12504             {
12505                 op         = op2->AsColon()->ThenNode();
12506                 opToDelete = op2->AsColon()->ElseNode();
12507             }
12508             else
12509             {
12510                 op         = op2->AsColon()->ElseNode();
12511                 opToDelete = op2->AsColon()->ThenNode();
12512             }
12513
12514             // Clear colon flags only if the qmark itself is not conditionaly executed
12515             if ((tree->gtFlags & GTF_COLON_COND) == 0)
12516             {
12517                 fgWalkTreePre(&op, gtClearColonCond);
12518             }
12519         }
12520
12521             goto DONE_FOLD;
12522
12523         default:
12524             break;
12525     }
12526
12527     /* The node is not foldable */
12528
12529     return tree;
12530
12531 DONE_FOLD:
12532
12533     /* The node has beeen folded into 'op' */
12534
12535     // If there was an assigment update, we just morphed it into
12536     // a use, update the flags appropriately
12537     if (op->gtOper == GT_LCL_VAR)
12538     {
12539         assert(tree->OperIs(GT_ASG) || (op->gtFlags & (GTF_VAR_USEASG | GTF_VAR_DEF)) == 0);
12540
12541         op->gtFlags &= ~(GTF_VAR_USEASG | GTF_VAR_DEF);
12542     }
12543
12544     op->gtNext = tree->gtNext;
12545     op->gtPrev = tree->gtPrev;
12546
12547     return op;
12548 }
12549
12550 //------------------------------------------------------------------------
12551 // gtTryRemoveBoxUpstreamEffects: given an unused value type box,
12552 //    try and remove the upstream allocation and unnecessary parts of
12553 //    the copy.
12554 //
12555 // Arguments:
12556 //    op  - the box node to optimize
12557 //    options - controls whether and how trees are modified
12558 //        (see notes)
12559 //
12560 // Return Value:
12561 //    A tree representing the original value to box, if removal
12562 //    is successful/possible (but see note). nullptr if removal fails.
12563 //
12564 // Notes:
12565 //    Value typed box gets special treatment because it has associated
12566 //    side effects that can be removed if the box result is not used.
12567 //
12568 //    By default (options == BR_REMOVE_AND_NARROW) this method will
12569 //    try and remove unnecessary trees and will try and reduce remaning
12570 //    operations to the minimal set, possibly narrowing the width of
12571 //    loads from the box source if it is a struct.
12572 //
12573 //    To perform a trial removal, pass BR_DONT_REMOVE. This can be
12574 //    useful to determine if this optimization should only be
12575 //    performed if some other conditions hold true.
12576 //
12577 //    To remove but not alter the access to the box source, pass
12578 //    BR_REMOVE_BUT_NOT_NARROW.
12579 //
12580 //    To remove and return the tree for the type handle used for
12581 //    the boxed newobj, pass BR_REMOVE_BUT_NOT_NARROW_WANT_TYPE_HANDLE.
12582 //    This can be useful when the only part of the box that is "live"
12583 //    is its type.
12584 //
12585 //    If removal fails, is is possible that a subsequent pass may be
12586 //    able to optimize.  Blocking side effects may now be minimized
12587 //    (null or bounds checks might have been removed) or might be
12588 //    better known (inline return placeholder updated with the actual
12589 //    return expression). So the box is perhaps best left as is to
12590 //    help trigger this re-examination.
12591
12592 GenTree* Compiler::gtTryRemoveBoxUpstreamEffects(GenTree* op, BoxRemovalOptions options)
12593 {
12594     assert(op->IsBoxedValue());
12595
12596     // grab related parts for the optimization
12597     GenTreeBox* box      = op->AsBox();
12598     GenTree*    asgStmt  = box->gtAsgStmtWhenInlinedBoxValue;
12599     GenTree*    copyStmt = box->gtCopyStmtWhenInlinedBoxValue;
12600
12601     assert(asgStmt->gtOper == GT_STMT);
12602     assert(copyStmt->gtOper == GT_STMT);
12603
12604     JITDUMP("gtTryRemoveBoxUpstreamEffects: %s to %s of BOX (valuetype)"
12605             " [%06u] (assign/newobj [%06u] copy [%06u])\n",
12606             (options == BR_DONT_REMOVE) ? "checking if it is possible" : "attempting",
12607             (options == BR_MAKE_LOCAL_COPY) ? "make local unboxed version" : "remove side effects", dspTreeID(op),
12608             dspTreeID(asgStmt), dspTreeID(copyStmt));
12609
12610     // If we don't recognize the form of the assign, bail.
12611     GenTree* asg = asgStmt->gtStmt.gtStmtExpr;
12612     if (asg->gtOper != GT_ASG)
12613     {
12614         JITDUMP(" bailing; unexpected assignment op %s\n", GenTree::OpName(asg->gtOper));
12615         return nullptr;
12616     }
12617
12618     // If we're eventually going to return the type handle, remember it now.
12619     GenTree* boxTypeHandle = nullptr;
12620     if ((options == BR_REMOVE_AND_NARROW_WANT_TYPE_HANDLE) || (options == BR_DONT_REMOVE_WANT_TYPE_HANDLE))
12621     {
12622         GenTree*   asgSrc     = asg->gtOp.gtOp2;
12623         genTreeOps asgSrcOper = asgSrc->OperGet();
12624
12625         // Allocation may be via AllocObj or via helper call, depending
12626         // on when this is invoked and whether the jit is using AllocObj
12627         // for R2R allocations.
12628         if (asgSrcOper == GT_ALLOCOBJ)
12629         {
12630             GenTreeAllocObj* allocObj = asgSrc->AsAllocObj();
12631             boxTypeHandle             = allocObj->gtOp.gtOp1;
12632         }
12633         else if (asgSrcOper == GT_CALL)
12634         {
12635             GenTreeCall* newobjCall = asgSrc->AsCall();
12636             GenTree*     newobjArgs = newobjCall->gtCallArgs;
12637
12638             // In R2R expansions the handle may not be an explicit operand to the helper,
12639             // so we can't remove the box.
12640             if (newobjArgs == nullptr)
12641             {
12642                 assert(newobjCall->IsHelperCall(this, CORINFO_HELP_READYTORUN_NEW));
12643                 JITDUMP(" bailing; newobj via R2R helper\n");
12644                 return nullptr;
12645             }
12646
12647             boxTypeHandle = newobjArgs->AsArgList()->Current();
12648         }
12649         else
12650         {
12651             unreached();
12652         }
12653
12654         assert(boxTypeHandle != nullptr);
12655     }
12656
12657     // If we don't recognize the form of the copy, bail.
12658     GenTree* copy = copyStmt->gtStmt.gtStmtExpr;
12659     if (copy->gtOper != GT_ASG)
12660     {
12661         // GT_RET_EXPR is a tolerable temporary failure.
12662         // The jit will revisit this optimization after
12663         // inlining is done.
12664         if (copy->gtOper == GT_RET_EXPR)
12665         {
12666             JITDUMP(" bailing; must wait for replacement of copy %s\n", GenTree::OpName(copy->gtOper));
12667         }
12668         else
12669         {
12670             // Anything else is a missed case we should
12671             // figure out how to handle.  One known case
12672             // is GT_COMMAs enclosing the GT_ASG we are
12673             // looking for.
12674             JITDUMP(" bailing; unexpected copy op %s\n", GenTree::OpName(copy->gtOper));
12675         }
12676         return nullptr;
12677     }
12678
12679     // Handle case where we are optimizing the box into a local copy
12680     if (options == BR_MAKE_LOCAL_COPY)
12681     {
12682         // Drill into the box to get at the box temp local and the box type
12683         GenTree* boxTemp = box->BoxOp();
12684         assert(boxTemp->IsLocal());
12685         const unsigned boxTempLcl = boxTemp->AsLclVar()->GetLclNum();
12686         assert(lvaTable[boxTempLcl].lvType == TYP_REF);
12687         CORINFO_CLASS_HANDLE boxClass = lvaTable[boxTempLcl].lvClassHnd;
12688         assert(boxClass != nullptr);
12689
12690         // Verify that the copyDst has the expected shape
12691         // (blk|obj|ind (add (boxTempLcl, ptr-size)))
12692         //
12693         // The shape here is constrained to the patterns we produce
12694         // over in impImportAndPushBox for the inlined box case.
12695         GenTree* copyDst = copy->gtOp.gtOp1;
12696
12697         if (!copyDst->OperIs(GT_BLK, GT_IND, GT_OBJ))
12698         {
12699             JITDUMP("Unexpected copy dest operator %s\n", GenTree::OpName(copyDst->gtOper));
12700             return nullptr;
12701         }
12702
12703         GenTree* copyDstAddr = copyDst->gtOp.gtOp1;
12704         if (copyDstAddr->OperGet() != GT_ADD)
12705         {
12706             JITDUMP("Unexpected copy dest address tree\n");
12707             return nullptr;
12708         }
12709
12710         GenTree* copyDstAddrOp1 = copyDstAddr->gtOp.gtOp1;
12711         if ((copyDstAddrOp1->OperGet() != GT_LCL_VAR) || (copyDstAddrOp1->gtLclVarCommon.gtLclNum != boxTempLcl))
12712         {
12713             JITDUMP("Unexpected copy dest address 1st addend\n");
12714             return nullptr;
12715         }
12716
12717         GenTree* copyDstAddrOp2 = copyDstAddr->gtOp.gtOp2;
12718         if (!copyDstAddrOp2->IsIntegralConst(TARGET_POINTER_SIZE))
12719         {
12720             JITDUMP("Unexpected copy dest address 2nd addend\n");
12721             return nullptr;
12722         }
12723
12724         // Screening checks have all passed. Do the transformation.
12725         //
12726         // Retype the box temp to be a struct
12727         JITDUMP("Retyping box temp V%02u to struct %s\n", boxTempLcl, eeGetClassName(boxClass));
12728         lvaTable[boxTempLcl].lvType   = TYP_UNDEF;
12729         const bool isUnsafeValueClass = false;
12730         lvaSetStruct(boxTempLcl, boxClass, isUnsafeValueClass);
12731         var_types boxTempType = lvaTable[boxTempLcl].lvType;
12732
12733         // Remove the newobj and assigment to box temp
12734         JITDUMP("Bashing NEWOBJ [%06u] to NOP\n", dspTreeID(asg));
12735         asg->gtBashToNOP();
12736
12737         // Update the copy from the value to be boxed to the box temp
12738         GenTree* newDst     = gtNewOperNode(GT_ADDR, TYP_BYREF, gtNewLclvNode(boxTempLcl, boxTempType));
12739         copyDst->gtOp.gtOp1 = newDst;
12740
12741         // Return the address of the now-struct typed box temp
12742         GenTree* retValue = gtNewOperNode(GT_ADDR, TYP_BYREF, gtNewLclvNode(boxTempLcl, boxTempType));
12743
12744         return retValue;
12745     }
12746
12747     // If the copy is a struct copy, make sure we know how to isolate
12748     // any source side effects.
12749     GenTree* copySrc = copy->gtOp.gtOp2;
12750
12751     // If the copy source is from a pending inline, wait for it to resolve.
12752     if (copySrc->gtOper == GT_RET_EXPR)
12753     {
12754         JITDUMP(" bailing; must wait for replacement of copy source %s\n", GenTree::OpName(copySrc->gtOper));
12755         return nullptr;
12756     }
12757
12758     bool hasSrcSideEffect = false;
12759     bool isStructCopy     = false;
12760
12761     if (gtTreeHasSideEffects(copySrc, GTF_SIDE_EFFECT))
12762     {
12763         hasSrcSideEffect = true;
12764
12765         if (varTypeIsStruct(copySrc->gtType))
12766         {
12767             isStructCopy = true;
12768
12769             if ((copySrc->gtOper != GT_OBJ) && (copySrc->gtOper != GT_IND) && (copySrc->gtOper != GT_FIELD))
12770             {
12771                 // We don't know how to handle other cases, yet.
12772                 JITDUMP(" bailing; unexpected copy source struct op with side effect %s\n",
12773                         GenTree::OpName(copySrc->gtOper));
12774                 return nullptr;
12775             }
12776         }
12777     }
12778
12779     // If this was a trial removal, we're done.
12780     if (options == BR_DONT_REMOVE)
12781     {
12782         return copySrc;
12783     }
12784
12785     if (options == BR_DONT_REMOVE_WANT_TYPE_HANDLE)
12786     {
12787         return boxTypeHandle;
12788     }
12789
12790     // Otherwise, proceed with the optimization.
12791     //
12792     // Change the assignment expression to a NOP.
12793     JITDUMP("\nBashing NEWOBJ [%06u] to NOP\n", dspTreeID(asg));
12794     asg->gtBashToNOP();
12795
12796     // Change the copy expression so it preserves key
12797     // source side effects.
12798     JITDUMP("\nBashing COPY [%06u]", dspTreeID(copy));
12799
12800     if (!hasSrcSideEffect)
12801     {
12802         // If there were no copy source side effects just bash
12803         // the copy to a NOP.
12804         copy->gtBashToNOP();
12805         JITDUMP(" to NOP; no source side effects.\n");
12806     }
12807     else if (!isStructCopy)
12808     {
12809         // For scalar types, go ahead and produce the
12810         // value as the copy is fairly cheap and likely
12811         // the optimizer can trim things down to just the
12812         // minimal side effect parts.
12813         copyStmt->gtStmt.gtStmtExpr = copySrc;
12814         JITDUMP(" to scalar read via [%06u]\n", dspTreeID(copySrc));
12815     }
12816     else
12817     {
12818         // For struct types read the first byte of the
12819         // source struct; there's no need to read the
12820         // entire thing, and no place to put it.
12821         assert(copySrc->gtOper == GT_OBJ || copySrc->gtOper == GT_IND || copySrc->gtOper == GT_FIELD);
12822         copyStmt->gtStmt.gtStmtExpr = copySrc;
12823
12824         if (options == BR_REMOVE_AND_NARROW || options == BR_REMOVE_AND_NARROW_WANT_TYPE_HANDLE)
12825         {
12826             JITDUMP(" to read first byte of struct via modified [%06u]\n", dspTreeID(copySrc));
12827             copySrc->ChangeOper(GT_IND);
12828             copySrc->gtType = TYP_BYTE;
12829         }
12830         else
12831         {
12832             JITDUMP(" to read entire struct via modified [%06u]\n", dspTreeID(copySrc));
12833         }
12834     }
12835
12836     if (fgStmtListThreaded)
12837     {
12838         fgSetStmtSeq(asgStmt);
12839         fgSetStmtSeq(copyStmt);
12840     }
12841
12842     // Box effects were successfully optimized.
12843
12844     if (options == BR_REMOVE_AND_NARROW_WANT_TYPE_HANDLE)
12845     {
12846         return boxTypeHandle;
12847     }
12848     else
12849     {
12850         return copySrc;
12851     }
12852 }
12853
12854 //------------------------------------------------------------------------
12855 // gtOptimizeEnumHasFlag: given the operands for a call to Enum.HasFlag,
12856 //    try and optimize the call to a simple and/compare tree.
12857 //
12858 // Arguments:
12859 //    thisOp  - first argument to the call
12860 //    flagOp  - second argument to the call
12861 //
12862 // Return Value:
12863 //    A new cmp/amd tree if successful. nullptr on failure.
12864 //
12865 // Notes:
12866 //    If successful, may allocate new temps and modify connected
12867 //    statements.
12868
12869 GenTree* Compiler::gtOptimizeEnumHasFlag(GenTree* thisOp, GenTree* flagOp)
12870 {
12871     JITDUMP("Considering optimizing call to Enum.HasFlag....\n");
12872
12873     // Operands must be boxes
12874     if (!thisOp->IsBoxedValue() || !flagOp->IsBoxedValue())
12875     {
12876         JITDUMP("bailing, need both inputs to be BOXes\n");
12877         return nullptr;
12878     }
12879
12880     // Operands must have same type
12881     bool                 isExactThis   = false;
12882     bool                 isNonNullThis = false;
12883     CORINFO_CLASS_HANDLE thisHnd       = gtGetClassHandle(thisOp, &isExactThis, &isNonNullThis);
12884
12885     if (thisHnd == nullptr)
12886     {
12887         JITDUMP("bailing, can't find type for 'this' operand\n");
12888         return nullptr;
12889     }
12890
12891     // A boxed thisOp should have exact type and non-null instance
12892     assert(isExactThis);
12893     assert(isNonNullThis);
12894
12895     bool                 isExactFlag   = false;
12896     bool                 isNonNullFlag = false;
12897     CORINFO_CLASS_HANDLE flagHnd       = gtGetClassHandle(flagOp, &isExactFlag, &isNonNullFlag);
12898
12899     if (flagHnd == nullptr)
12900     {
12901         JITDUMP("bailing, can't find type for 'flag' operand\n");
12902         return nullptr;
12903     }
12904
12905     // A boxed flagOp should have exact type and non-null instance
12906     assert(isExactFlag);
12907     assert(isNonNullFlag);
12908
12909     if (flagHnd != thisHnd)
12910     {
12911         JITDUMP("bailing, operand types differ\n");
12912         return nullptr;
12913     }
12914
12915     // If we have a shared type instance we can't safely check type
12916     // equality, so bail.
12917     DWORD classAttribs = info.compCompHnd->getClassAttribs(thisHnd);
12918     if (classAttribs & CORINFO_FLG_SHAREDINST)
12919     {
12920         JITDUMP("bailing, have shared instance type\n");
12921         return nullptr;
12922     }
12923
12924     // Simulate removing the box for thisOP. We need to know that it can
12925     // be safely removed before we can optimize.
12926     GenTree* thisVal = gtTryRemoveBoxUpstreamEffects(thisOp, BR_DONT_REMOVE);
12927     if (thisVal == nullptr)
12928     {
12929         // Note we may fail here if the this operand comes from
12930         // a call. We should be able to retry this post-inlining.
12931         JITDUMP("bailing, can't undo box of 'this' operand\n");
12932         return nullptr;
12933     }
12934
12935     GenTree* flagVal = gtTryRemoveBoxUpstreamEffects(flagOp, BR_REMOVE_BUT_NOT_NARROW);
12936     if (flagVal == nullptr)
12937     {
12938         // Note we may fail here if the flag operand comes from
12939         // a call. We should be able to retry this post-inlining.
12940         JITDUMP("bailing, can't undo box of 'flag' operand\n");
12941         return nullptr;
12942     }
12943
12944     // Yes, both boxes can be cleaned up. Optimize.
12945     JITDUMP("Optimizing call to Enum.HasFlag\n");
12946
12947     // Undo the boxing of thisOp and prepare to operate directly
12948     // on the original enum values.
12949     thisVal = gtTryRemoveBoxUpstreamEffects(thisOp, BR_REMOVE_BUT_NOT_NARROW);
12950
12951     // Our trial removal above should guarantee successful removal here.
12952     assert(thisVal != nullptr);
12953
12954     // We should have a consistent view of the type
12955     var_types type = thisVal->TypeGet();
12956     assert(type == flagVal->TypeGet());
12957
12958     // The thisVal and flagVal trees come from earlier statements.
12959     //
12960     // Unless they are invariant values, we need to evaluate them both
12961     // to temps at those points to safely transmit the values here.
12962     //
12963     // Also we need to use the flag twice, so we need two trees for it.
12964     GenTree* thisValOpt     = nullptr;
12965     GenTree* flagValOpt     = nullptr;
12966     GenTree* flagValOptCopy = nullptr;
12967
12968     if (thisVal->IsIntegralConst())
12969     {
12970         thisValOpt = gtClone(thisVal);
12971         assert(thisValOpt != nullptr);
12972     }
12973     else
12974     {
12975         const unsigned thisTmp         = lvaGrabTemp(true DEBUGARG("Enum:HasFlag this temp"));
12976         GenTree*       thisAsg         = gtNewTempAssign(thisTmp, thisVal);
12977         GenTree*       thisAsgStmt     = thisOp->AsBox()->gtCopyStmtWhenInlinedBoxValue;
12978         thisAsgStmt->gtStmt.gtStmtExpr = thisAsg;
12979         thisValOpt                     = gtNewLclvNode(thisTmp, type);
12980     }
12981
12982     if (flagVal->IsIntegralConst())
12983     {
12984         flagValOpt = gtClone(flagVal);
12985         assert(flagValOpt != nullptr);
12986         flagValOptCopy = gtClone(flagVal);
12987         assert(flagValOptCopy != nullptr);
12988     }
12989     else
12990     {
12991         const unsigned flagTmp         = lvaGrabTemp(true DEBUGARG("Enum:HasFlag flag temp"));
12992         GenTree*       flagAsg         = gtNewTempAssign(flagTmp, flagVal);
12993         GenTree*       flagAsgStmt     = flagOp->AsBox()->gtCopyStmtWhenInlinedBoxValue;
12994         flagAsgStmt->gtStmt.gtStmtExpr = flagAsg;
12995         flagValOpt                     = gtNewLclvNode(flagTmp, type);
12996         flagValOptCopy                 = gtNewLclvNode(flagTmp, type);
12997     }
12998
12999     // Turn the call into (thisValTmp & flagTmp) == flagTmp.
13000     GenTree* andTree = gtNewOperNode(GT_AND, type, thisValOpt, flagValOpt);
13001     GenTree* cmpTree = gtNewOperNode(GT_EQ, TYP_INT, andTree, flagValOptCopy);
13002
13003     JITDUMP("Optimized call to Enum.HasFlag\n");
13004
13005     return cmpTree;
13006 }
13007
13008 /*****************************************************************************
13009  *
13010  *  Fold the given constant tree.
13011  */
13012
13013 #ifdef _PREFAST_
13014 #pragma warning(push)
13015 #pragma warning(disable : 21000) // Suppress PREFast warning about overly large function
13016 #endif
13017 GenTree* Compiler::gtFoldExprConst(GenTree* tree)
13018 {
13019     unsigned kind = tree->OperKind();
13020
13021     SSIZE_T       i1, i2, itemp;
13022     INT64         lval1, lval2, ltemp;
13023     float         f1, f2;
13024     double        d1, d2;
13025     var_types     switchType;
13026     FieldSeqNode* fieldSeq = FieldSeqStore::NotAField(); // default unless we override it when folding
13027
13028     assert(kind & (GTK_UNOP | GTK_BINOP));
13029
13030     GenTree* op1 = tree->gtOp.gtOp1;
13031     GenTree* op2 = tree->gtGetOp2IfPresent();
13032
13033     if (!opts.OptEnabled(CLFLG_CONSTANTFOLD))
13034     {
13035         return tree;
13036     }
13037
13038     if (tree->OperGet() == GT_NOP)
13039     {
13040         return tree;
13041     }
13042
13043 #ifdef FEATURE_SIMD
13044     if (tree->OperGet() == GT_SIMD)
13045     {
13046         return tree;
13047     }
13048 #endif // FEATURE_SIMD
13049
13050     if (tree->gtOper == GT_ALLOCOBJ)
13051     {
13052         return tree;
13053     }
13054
13055     if (tree->gtOper == GT_RUNTIMELOOKUP)
13056     {
13057         return tree;
13058     }
13059
13060     if (kind & GTK_UNOP)
13061     {
13062         assert(op1->OperKind() & GTK_CONST);
13063
13064         switch (op1->gtType)
13065         {
13066             case TYP_INT:
13067
13068                 /* Fold constant INT unary operator */
13069
13070                 if (!op1->gtIntCon.ImmedValCanBeFolded(this, tree->OperGet()))
13071                 {
13072                     return tree;
13073                 }
13074
13075                 i1 = (int)op1->gtIntCon.gtIconVal;
13076
13077                 // If we fold a unary oper, then the folded constant
13078                 // is considered a ConstantIndexField if op1 was one
13079                 //
13080
13081                 if ((op1->gtIntCon.gtFieldSeq != nullptr) && op1->gtIntCon.gtFieldSeq->IsConstantIndexFieldSeq())
13082                 {
13083                     fieldSeq = op1->gtIntCon.gtFieldSeq;
13084                 }
13085
13086                 switch (tree->gtOper)
13087                 {
13088                     case GT_NOT:
13089                         i1 = ~i1;
13090                         break;
13091
13092                     case GT_NEG:
13093                         i1 = -i1;
13094                         break;
13095
13096                     case GT_BSWAP:
13097                         i1 = ((i1 >> 24) & 0xFF) | ((i1 >> 8) & 0xFF00) | ((i1 << 8) & 0xFF0000) |
13098                              ((i1 << 24) & 0xFF000000);
13099                         break;
13100
13101                     case GT_BSWAP16:
13102                         i1 = ((i1 >> 8) & 0xFF) | ((i1 << 8) & 0xFF00);
13103                         break;
13104
13105                     case GT_CAST:
13106                         // assert (genActualType(tree->CastToType()) == tree->gtType);
13107                         switch (tree->CastToType())
13108                         {
13109                             case TYP_BYTE:
13110                                 itemp = INT32(INT8(i1));
13111                                 goto CHK_OVF;
13112
13113                             case TYP_SHORT:
13114                                 itemp = INT32(INT16(i1));
13115                             CHK_OVF:
13116                                 if (tree->gtOverflow() && ((itemp != i1) || ((tree->gtFlags & GTF_UNSIGNED) && i1 < 0)))
13117                                 {
13118                                     goto INT_OVF;
13119                                 }
13120                                 i1 = itemp;
13121                                 goto CNS_INT;
13122
13123                             case TYP_USHORT:
13124                                 itemp = INT32(UINT16(i1));
13125                                 if (tree->gtOverflow())
13126                                 {
13127                                     if (itemp != i1)
13128                                     {
13129                                         goto INT_OVF;
13130                                     }
13131                                 }
13132                                 i1 = itemp;
13133                                 goto CNS_INT;
13134
13135                             case TYP_BOOL:
13136                             case TYP_UBYTE:
13137                                 itemp = INT32(UINT8(i1));
13138                                 if (tree->gtOverflow())
13139                                 {
13140                                     if (itemp != i1)
13141                                     {
13142                                         goto INT_OVF;
13143                                     }
13144                                 }
13145                                 i1 = itemp;
13146                                 goto CNS_INT;
13147
13148                             case TYP_UINT:
13149                                 if (!(tree->gtFlags & GTF_UNSIGNED) && tree->gtOverflow() && i1 < 0)
13150                                 {
13151                                     goto INT_OVF;
13152                                 }
13153                                 goto CNS_INT;
13154
13155                             case TYP_INT:
13156                                 if ((tree->gtFlags & GTF_UNSIGNED) && tree->gtOverflow() && i1 < 0)
13157                                 {
13158                                     goto INT_OVF;
13159                                 }
13160                                 goto CNS_INT;
13161
13162                             case TYP_ULONG:
13163                                 if (tree->IsUnsigned())
13164                                 {
13165                                     lval1 = UINT64(UINT32(i1));
13166                                 }
13167                                 else
13168                                 {
13169                                     if (tree->gtOverflow() && (i1 < 0))
13170                                     {
13171                                         goto LNG_OVF;
13172                                     }
13173                                     lval1 = UINT64(INT32(i1));
13174                                 }
13175                                 goto CNS_LONG;
13176
13177                             case TYP_LONG:
13178                                 if (tree->IsUnsigned())
13179                                 {
13180                                     lval1 = INT64(UINT32(i1));
13181                                 }
13182                                 else
13183                                 {
13184                                     lval1 = INT64(INT32(i1));
13185                                 }
13186                                 goto CNS_LONG;
13187
13188                             case TYP_FLOAT:
13189                                 if (tree->gtFlags & GTF_UNSIGNED)
13190                                 {
13191                                     f1 = forceCastToFloat(UINT32(i1));
13192                                 }
13193                                 else
13194                                 {
13195                                     f1 = forceCastToFloat(INT32(i1));
13196                                 }
13197                                 d1 = f1;
13198                                 goto CNS_DOUBLE;
13199
13200                             case TYP_DOUBLE:
13201                                 if (tree->gtFlags & GTF_UNSIGNED)
13202                                 {
13203                                     d1 = (double)UINT32(i1);
13204                                 }
13205                                 else
13206                                 {
13207                                     d1 = (double)INT32(i1);
13208                                 }
13209                                 goto CNS_DOUBLE;
13210
13211                             default:
13212                                 assert(!"BAD_TYP");
13213                                 break;
13214                         }
13215                         return tree;
13216
13217                     default:
13218                         return tree;
13219                 }
13220
13221                 goto CNS_INT;
13222
13223             case TYP_LONG:
13224
13225                 /* Fold constant LONG unary operator */
13226
13227                 if (!op1->gtIntConCommon.ImmedValCanBeFolded(this, tree->OperGet()))
13228                 {
13229                     return tree;
13230                 }
13231
13232                 lval1 = op1->gtIntConCommon.LngValue();
13233
13234                 switch (tree->gtOper)
13235                 {
13236                     case GT_NOT:
13237                         lval1 = ~lval1;
13238                         break;
13239
13240                     case GT_NEG:
13241                         lval1 = -lval1;
13242                         break;
13243
13244                     case GT_BSWAP:
13245                         lval1 = ((lval1 >> 56) & 0xFF) | ((lval1 >> 40) & 0xFF00) | ((lval1 >> 24) & 0xFF0000) |
13246                                 ((lval1 >> 8) & 0xFF000000) | ((lval1 << 8) & 0xFF00000000) |
13247                                 ((lval1 << 24) & 0xFF0000000000) | ((lval1 << 40) & 0xFF000000000000) |
13248                                 ((lval1 << 56) & 0xFF00000000000000);
13249                         break;
13250
13251                     case GT_CAST:
13252                         assert(genActualType(tree->CastToType()) == tree->gtType);
13253                         switch (tree->CastToType())
13254                         {
13255                             case TYP_BYTE:
13256                                 i1 = INT32(INT8(lval1));
13257                                 goto CHECK_INT_OVERFLOW;
13258
13259                             case TYP_SHORT:
13260                                 i1 = INT32(INT16(lval1));
13261                                 goto CHECK_INT_OVERFLOW;
13262
13263                             case TYP_USHORT:
13264                                 i1 = INT32(UINT16(lval1));
13265                                 goto CHECK_UINT_OVERFLOW;
13266
13267                             case TYP_UBYTE:
13268                                 i1 = INT32(UINT8(lval1));
13269                                 goto CHECK_UINT_OVERFLOW;
13270
13271                             case TYP_INT:
13272                                 i1 = INT32(lval1);
13273
13274                             CHECK_INT_OVERFLOW:
13275                                 if (tree->gtOverflow())
13276                                 {
13277                                     if (i1 != lval1)
13278                                     {
13279                                         goto INT_OVF;
13280                                     }
13281                                     if ((tree->gtFlags & GTF_UNSIGNED) && i1 < 0)
13282                                     {
13283                                         goto INT_OVF;
13284                                     }
13285                                 }
13286                                 goto CNS_INT;
13287
13288                             case TYP_UINT:
13289                                 i1 = UINT32(lval1);
13290
13291                             CHECK_UINT_OVERFLOW:
13292                                 if (tree->gtOverflow() && UINT32(i1) != lval1)
13293                                 {
13294                                     goto INT_OVF;
13295                                 }
13296                                 goto CNS_INT;
13297
13298                             case TYP_ULONG:
13299                                 if (!(tree->gtFlags & GTF_UNSIGNED) && tree->gtOverflow() && lval1 < 0)
13300                                 {
13301                                     goto LNG_OVF;
13302                                 }
13303                                 goto CNS_LONG;
13304
13305                             case TYP_LONG:
13306                                 if ((tree->gtFlags & GTF_UNSIGNED) && tree->gtOverflow() && lval1 < 0)
13307                                 {
13308                                     goto LNG_OVF;
13309                                 }
13310                                 goto CNS_LONG;
13311
13312                             case TYP_FLOAT:
13313                             case TYP_DOUBLE:
13314                                 if ((tree->gtFlags & GTF_UNSIGNED) && lval1 < 0)
13315                                 {
13316                                     d1 = FloatingPointUtils::convertUInt64ToDouble((unsigned __int64)lval1);
13317                                 }
13318                                 else
13319                                 {
13320                                     d1 = (double)lval1;
13321                                 }
13322
13323                                 if (tree->CastToType() == TYP_FLOAT)
13324                                 {
13325                                     f1 = forceCastToFloat(d1); // truncate precision
13326                                     d1 = f1;
13327                                 }
13328                                 goto CNS_DOUBLE;
13329                             default:
13330                                 assert(!"BAD_TYP");
13331                                 break;
13332                         }
13333                         return tree;
13334
13335                     default:
13336                         return tree;
13337                 }
13338
13339                 goto CNS_LONG;
13340
13341             case TYP_FLOAT:
13342             case TYP_DOUBLE:
13343                 assert(op1->gtOper == GT_CNS_DBL);
13344
13345                 /* Fold constant DOUBLE unary operator */
13346
13347                 d1 = op1->gtDblCon.gtDconVal;
13348
13349                 switch (tree->gtOper)
13350                 {
13351                     case GT_NEG:
13352                         d1 = -d1;
13353                         break;
13354
13355                     case GT_CAST:
13356
13357                         if (tree->gtOverflowEx())
13358                         {
13359                             return tree;
13360                         }
13361
13362                         assert(genActualType(tree->CastToType()) == tree->gtType);
13363
13364                         if ((op1->gtType == TYP_FLOAT && !_finite(forceCastToFloat(d1))) ||
13365                             (op1->gtType == TYP_DOUBLE && !_finite(d1)))
13366                         {
13367                             // The floating point constant is not finite.  The ECMA spec says, in
13368                             // III 3.27, that "...if overflow occurs converting a floating point type
13369                             // to an integer, ..., the value returned is unspecified."  However, it would
13370                             // at least be desirable to have the same value returned for casting an overflowing
13371                             // constant to an int as would obtained by passing that constant as a parameter
13372                             // then casting that parameter to an int type.  We will assume that the C compiler's
13373                             // cast logic will yield the desired result (and trust testing to tell otherwise).
13374                             // Cross-compilation is an issue here; if that becomes an important scenario, we should
13375                             // capture the target-specific values of overflow casts to the various integral types as
13376                             // constants in a target-specific function.
13377                             CLANG_FORMAT_COMMENT_ANCHOR;
13378
13379                             // Don't fold conversions of +inf/-inf to integral value on all platforms
13380                             // as the value returned by JIT helper doesn't match with the C compiler's cast result.
13381                             // We want the behavior to be same with or without folding.
13382                             return tree;
13383                         }
13384
13385                         if (d1 <= -1.0 && varTypeIsUnsigned(tree->CastToType()))
13386                         {
13387                             // Don't fold conversions of these cases becasue the result is unspecified per ECMA spec
13388                             // and the native math doing the fold doesn't match the run-time computation on all
13389                             // platforms.
13390                             // We want the behavior to be same with or without folding.
13391                             return tree;
13392                         }
13393
13394                         switch (tree->CastToType())
13395                         {
13396                             case TYP_BYTE:
13397                                 i1 = INT32(INT8(d1));
13398                                 goto CNS_INT;
13399
13400                             case TYP_SHORT:
13401                                 i1 = INT32(INT16(d1));
13402                                 goto CNS_INT;
13403
13404                             case TYP_USHORT:
13405                                 i1 = INT32(UINT16(d1));
13406                                 goto CNS_INT;
13407
13408                             case TYP_UBYTE:
13409                                 i1 = INT32(UINT8(d1));
13410                                 goto CNS_INT;
13411
13412                             case TYP_INT:
13413                                 i1 = INT32(d1);
13414                                 goto CNS_INT;
13415
13416                             case TYP_UINT:
13417                                 i1 = forceCastToUInt32(d1);
13418                                 goto CNS_INT;
13419
13420                             case TYP_LONG:
13421                                 lval1 = INT64(d1);
13422                                 goto CNS_LONG;
13423
13424                             case TYP_ULONG:
13425                                 lval1 = FloatingPointUtils::convertDoubleToUInt64(d1);
13426                                 goto CNS_LONG;
13427
13428                             case TYP_FLOAT:
13429                                 d1 = forceCastToFloat(d1);
13430                                 goto CNS_DOUBLE;
13431
13432                             case TYP_DOUBLE:
13433                                 if (op1->gtType == TYP_FLOAT)
13434                                 {
13435                                     d1 = forceCastToFloat(d1); // truncate precision
13436                                 }
13437                                 goto CNS_DOUBLE; // redundant cast
13438
13439                             default:
13440                                 assert(!"BAD_TYP");
13441                                 break;
13442                         }
13443                         return tree;
13444
13445                     default:
13446                         return tree;
13447                 }
13448                 goto CNS_DOUBLE;
13449
13450             default:
13451                 /* not a foldable typ - e.g. RET const */
13452                 return tree;
13453         }
13454     }
13455
13456     /* We have a binary operator */
13457
13458     assert(kind & GTK_BINOP);
13459     assert(op2);
13460     assert(op1->OperKind() & GTK_CONST);
13461     assert(op2->OperKind() & GTK_CONST);
13462
13463     if (tree->gtOper == GT_COMMA)
13464     {
13465         return op2;
13466     }
13467
13468     if (tree->OperIsAnyList())
13469     {
13470         return tree;
13471     }
13472
13473     switchType = op1->gtType;
13474
13475     // Normally we will just switch on op1 types, but for the case where
13476     //  only op2 is a GC type and op1 is not a GC type, we use the op2 type.
13477     //  This makes us handle this as a case of folding for GC type.
13478     //
13479     if (varTypeIsGC(op2->gtType) && !varTypeIsGC(op1->gtType))
13480     {
13481         switchType = op2->gtType;
13482     }
13483
13484     switch (switchType)
13485     {
13486
13487         /*-------------------------------------------------------------------------
13488          * Fold constant REF of BYREF binary operator
13489          * These can only be comparisons or null pointers
13490          */
13491
13492         case TYP_REF:
13493
13494             /* String nodes are an RVA at this point */
13495
13496             if (op1->gtOper == GT_CNS_STR || op2->gtOper == GT_CNS_STR)
13497             {
13498                 return tree;
13499             }
13500
13501             __fallthrough;
13502
13503         case TYP_BYREF:
13504
13505             i1 = op1->gtIntConCommon.IconValue();
13506             i2 = op2->gtIntConCommon.IconValue();
13507
13508             switch (tree->gtOper)
13509             {
13510                 case GT_EQ:
13511                     i1 = (i1 == i2);
13512                     goto FOLD_COND;
13513
13514                 case GT_NE:
13515                     i1 = (i1 != i2);
13516                     goto FOLD_COND;
13517
13518                 case GT_ADD:
13519                     noway_assert(tree->gtType != TYP_REF);
13520                     // We only fold a GT_ADD that involves a null reference.
13521                     if (((op1->TypeGet() == TYP_REF) && (i1 == 0)) || ((op2->TypeGet() == TYP_REF) && (i2 == 0)))
13522                     {
13523 #ifdef DEBUG
13524                         if (verbose)
13525                         {
13526                             printf("\nFolding operator with constant nodes into a constant:\n");
13527                             gtDispTree(tree);
13528                         }
13529 #endif
13530                         // Fold into GT_IND of null byref
13531                         tree->ChangeOperConst(GT_CNS_INT);
13532                         tree->gtType              = TYP_BYREF;
13533                         tree->gtIntCon.gtIconVal  = 0;
13534                         tree->gtIntCon.gtFieldSeq = FieldSeqStore::NotAField();
13535                         if (vnStore != nullptr)
13536                         {
13537                             fgValueNumberTreeConst(tree);
13538                         }
13539 #ifdef DEBUG
13540                         if (verbose)
13541                         {
13542                             printf("\nFolded to null byref:\n");
13543                             gtDispTree(tree);
13544                         }
13545 #endif
13546                         goto DONE;
13547                     }
13548
13549                 default:
13550                     break;
13551             }
13552
13553             return tree;
13554
13555         /*-------------------------------------------------------------------------
13556          * Fold constant INT binary operator
13557          */
13558
13559         case TYP_INT:
13560
13561             if (tree->OperIsCompare() && (tree->gtType == TYP_BYTE))
13562             {
13563                 tree->gtType = TYP_INT;
13564             }
13565
13566             assert(tree->gtType == TYP_INT || varTypeIsGC(tree->TypeGet()) || tree->gtOper == GT_MKREFANY);
13567
13568             // No GC pointer types should be folded here...
13569             //
13570             assert(!varTypeIsGC(op1->gtType) && !varTypeIsGC(op2->gtType));
13571
13572             if (!op1->gtIntConCommon.ImmedValCanBeFolded(this, tree->OperGet()))
13573             {
13574                 return tree;
13575             }
13576
13577             if (!op2->gtIntConCommon.ImmedValCanBeFolded(this, tree->OperGet()))
13578             {
13579                 return tree;
13580             }
13581
13582             i1 = op1->gtIntConCommon.IconValue();
13583             i2 = op2->gtIntConCommon.IconValue();
13584
13585             switch (tree->gtOper)
13586             {
13587                 case GT_EQ:
13588                     i1 = (INT32(i1) == INT32(i2));
13589                     break;
13590                 case GT_NE:
13591                     i1 = (INT32(i1) != INT32(i2));
13592                     break;
13593
13594                 case GT_LT:
13595                     if (tree->gtFlags & GTF_UNSIGNED)
13596                     {
13597                         i1 = (UINT32(i1) < UINT32(i2));
13598                     }
13599                     else
13600                     {
13601                         i1 = (INT32(i1) < INT32(i2));
13602                     }
13603                     break;
13604
13605                 case GT_LE:
13606                     if (tree->gtFlags & GTF_UNSIGNED)
13607                     {
13608                         i1 = (UINT32(i1) <= UINT32(i2));
13609                     }
13610                     else
13611                     {
13612                         i1 = (INT32(i1) <= INT32(i2));
13613                     }
13614                     break;
13615
13616                 case GT_GE:
13617                     if (tree->gtFlags & GTF_UNSIGNED)
13618                     {
13619                         i1 = (UINT32(i1) >= UINT32(i2));
13620                     }
13621                     else
13622                     {
13623                         i1 = (INT32(i1) >= INT32(i2));
13624                     }
13625                     break;
13626
13627                 case GT_GT:
13628                     if (tree->gtFlags & GTF_UNSIGNED)
13629                     {
13630                         i1 = (UINT32(i1) > UINT32(i2));
13631                     }
13632                     else
13633                     {
13634                         i1 = (INT32(i1) > INT32(i2));
13635                     }
13636                     break;
13637
13638                 case GT_ADD:
13639                     itemp = i1 + i2;
13640                     if (tree->gtOverflow())
13641                     {
13642                         if (tree->gtFlags & GTF_UNSIGNED)
13643                         {
13644                             if (INT64(UINT32(itemp)) != INT64(UINT32(i1)) + INT64(UINT32(i2)))
13645                             {
13646                                 goto INT_OVF;
13647                             }
13648                         }
13649                         else
13650                         {
13651                             if (INT64(INT32(itemp)) != INT64(INT32(i1)) + INT64(INT32(i2)))
13652                             {
13653                                 goto INT_OVF;
13654                             }
13655                         }
13656                     }
13657                     i1       = itemp;
13658                     fieldSeq = GetFieldSeqStore()->Append(op1->gtIntCon.gtFieldSeq, op2->gtIntCon.gtFieldSeq);
13659                     break;
13660                 case GT_SUB:
13661                     itemp = i1 - i2;
13662                     if (tree->gtOverflow())
13663                     {
13664                         if (tree->gtFlags & GTF_UNSIGNED)
13665                         {
13666                             if (INT64(UINT32(itemp)) != ((INT64)((UINT32)i1) - (INT64)((UINT32)i2)))
13667                             {
13668                                 goto INT_OVF;
13669                             }
13670                         }
13671                         else
13672                         {
13673                             if (INT64(INT32(itemp)) != INT64(INT32(i1)) - INT64(INT32(i2)))
13674                             {
13675                                 goto INT_OVF;
13676                             }
13677                         }
13678                     }
13679                     i1 = itemp;
13680                     break;
13681                 case GT_MUL:
13682                     itemp = i1 * i2;
13683                     if (tree->gtOverflow())
13684                     {
13685                         if (tree->gtFlags & GTF_UNSIGNED)
13686                         {
13687                             if (INT64(UINT32(itemp)) != ((INT64)((UINT32)i1) * (INT64)((UINT32)i2)))
13688                             {
13689                                 goto INT_OVF;
13690                             }
13691                         }
13692                         else
13693                         {
13694                             if (INT64(INT32(itemp)) != INT64(INT32(i1)) * INT64(INT32(i2)))
13695                             {
13696                                 goto INT_OVF;
13697                             }
13698                         }
13699                     }
13700                     // For the very particular case of the "constant array index" pseudo-field, we
13701                     // assume that multiplication is by the field width, and preserves that field.
13702                     // This could obviously be made more robust by a more complicated set of annotations...
13703                     if ((op1->gtIntCon.gtFieldSeq != nullptr) && op1->gtIntCon.gtFieldSeq->IsConstantIndexFieldSeq())
13704                     {
13705                         assert(op2->gtIntCon.gtFieldSeq == FieldSeqStore::NotAField());
13706                         fieldSeq = op1->gtIntCon.gtFieldSeq;
13707                     }
13708                     else if ((op2->gtIntCon.gtFieldSeq != nullptr) &&
13709                              op2->gtIntCon.gtFieldSeq->IsConstantIndexFieldSeq())
13710                     {
13711                         assert(op1->gtIntCon.gtFieldSeq == FieldSeqStore::NotAField());
13712                         fieldSeq = op2->gtIntCon.gtFieldSeq;
13713                     }
13714                     i1 = itemp;
13715                     break;
13716
13717                 case GT_OR:
13718                     i1 |= i2;
13719                     break;
13720                 case GT_XOR:
13721                     i1 ^= i2;
13722                     break;
13723                 case GT_AND:
13724                     i1 &= i2;
13725                     break;
13726
13727                 case GT_LSH:
13728                     i1 <<= (i2 & 0x1f);
13729                     break;
13730                 case GT_RSH:
13731                     i1 >>= (i2 & 0x1f);
13732                     break;
13733                 case GT_RSZ:
13734                     /* logical shift -> make it unsigned to not propagate the sign bit */
13735                     i1 = UINT32(i1) >> (i2 & 0x1f);
13736                     break;
13737                 case GT_ROL:
13738                     i1 = (i1 << (i2 & 0x1f)) | (UINT32(i1) >> ((32 - i2) & 0x1f));
13739                     break;
13740                 case GT_ROR:
13741                     i1 = (i1 << ((32 - i2) & 0x1f)) | (UINT32(i1) >> (i2 & 0x1f));
13742                     break;
13743
13744                 /* DIV and MOD can generate an INT 0 - if division by 0
13745                  * or overflow - when dividing MIN by -1 */
13746
13747                 case GT_DIV:
13748                 case GT_MOD:
13749                 case GT_UDIV:
13750                 case GT_UMOD:
13751                     if (INT32(i2) == 0)
13752                     {
13753                         // Division by zero:
13754                         // We have to evaluate this expression and throw an exception
13755                         return tree;
13756                     }
13757                     else if ((INT32(i2) == -1) && (UINT32(i1) == 0x80000000))
13758                     {
13759                         // Overflow Division:
13760                         // We have to evaluate this expression and throw an exception
13761                         return tree;
13762                     }
13763
13764                     if (tree->gtOper == GT_DIV)
13765                     {
13766                         i1 = INT32(i1) / INT32(i2);
13767                     }
13768                     else if (tree->gtOper == GT_MOD)
13769                     {
13770                         i1 = INT32(i1) % INT32(i2);
13771                     }
13772                     else if (tree->gtOper == GT_UDIV)
13773                     {
13774                         i1 = UINT32(i1) / UINT32(i2);
13775                     }
13776                     else
13777                     {
13778                         assert(tree->gtOper == GT_UMOD);
13779                         i1 = UINT32(i1) % UINT32(i2);
13780                     }
13781                     break;
13782
13783                 default:
13784                     return tree;
13785             }
13786
13787         /* We get here after folding to a GT_CNS_INT type
13788          * change the node to the new type / value and make sure the node sizes are OK */
13789         CNS_INT:
13790         FOLD_COND:
13791
13792 #ifdef DEBUG
13793             if (verbose)
13794             {
13795                 printf("\nFolding operator with constant nodes into a constant:\n");
13796                 gtDispTree(tree);
13797             }
13798 #endif
13799
13800 #ifdef _TARGET_64BIT_
13801             // Some operations are performed as 64 bit instead of 32 bit so the upper 32 bits
13802             // need to be discarded. Since constant values are stored as ssize_t and the node
13803             // has TYP_INT the result needs to be sign extended rather than zero extended.
13804             i1 = INT32(i1);
13805 #endif // _TARGET_64BIT_
13806
13807             /* Also all conditional folding jumps here since the node hanging from
13808              * GT_JTRUE has to be a GT_CNS_INT - value 0 or 1 */
13809
13810             tree->ChangeOperConst(GT_CNS_INT);
13811             tree->gtType              = TYP_INT;
13812             tree->gtIntCon.gtIconVal  = i1;
13813             tree->gtIntCon.gtFieldSeq = fieldSeq;
13814             if (vnStore != nullptr)
13815             {
13816                 fgValueNumberTreeConst(tree);
13817             }
13818 #ifdef DEBUG
13819             if (verbose)
13820             {
13821                 printf("Bashed to int constant:\n");
13822                 gtDispTree(tree);
13823             }
13824 #endif
13825             goto DONE;
13826
13827         /* This operation is going to cause an overflow exception. Morph into
13828            an overflow helper. Put a dummy constant value for code generation.
13829
13830            We could remove all subsequent trees in the current basic block,
13831            unless this node is a child of GT_COLON
13832
13833            NOTE: Since the folded value is not constant we should not change the
13834                  "tree" node - otherwise we confuse the logic that checks if the folding
13835                  was successful - instead use one of the operands, e.g. op1
13836          */
13837
13838         LNG_OVF:
13839             // Don't fold overflow operations if not global morph phase.
13840             // The reason for this is that this optimization is replacing a gentree node
13841             // with another new gentree node. Say a GT_CALL(arglist) has one 'arg'
13842             // involving overflow arithmetic.  During assertion prop, it is possible
13843             // that the 'arg' could be constant folded and the result could lead to an
13844             // overflow.  In such a case 'arg' will get replaced with GT_COMMA node
13845             // but fgMorphArgs() - see the logic around "if(lateArgsComputed)" - doesn't
13846             // update args table. For this reason this optimization is enabled only
13847             // for global morphing phase.
13848             //
13849             // TODO-CQ: Once fgMorphArgs() is fixed this restriction could be removed.
13850             CLANG_FORMAT_COMMENT_ANCHOR;
13851
13852             if (!fgGlobalMorph)
13853             {
13854                 assert(tree->gtOverflow());
13855                 return tree;
13856             }
13857
13858             op1 = gtNewLconNode(0);
13859             if (vnStore != nullptr)
13860             {
13861                 op1->gtVNPair.SetBoth(vnStore->VNZeroForType(TYP_LONG));
13862             }
13863             goto OVF;
13864
13865         INT_OVF:
13866             // Don't fold overflow operations if not global morph phase.
13867             // The reason for this is that this optimization is replacing a gentree node
13868             // with another new gentree node. Say a GT_CALL(arglist) has one 'arg'
13869             // involving overflow arithmetic.  During assertion prop, it is possible
13870             // that the 'arg' could be constant folded and the result could lead to an
13871             // overflow.  In such a case 'arg' will get replaced with GT_COMMA node
13872             // but fgMorphArgs() - see the logic around "if(lateArgsComputed)" - doesn't
13873             // update args table. For this reason this optimization is enabled only
13874             // for global morphing phase.
13875             //
13876             // TODO-CQ: Once fgMorphArgs() is fixed this restriction could be removed.
13877
13878             if (!fgGlobalMorph)
13879             {
13880                 assert(tree->gtOverflow());
13881                 return tree;
13882             }
13883
13884             op1 = gtNewIconNode(0);
13885             if (vnStore != nullptr)
13886             {
13887                 op1->gtVNPair.SetBoth(vnStore->VNZeroForType(TYP_INT));
13888             }
13889             goto OVF;
13890
13891         OVF:
13892 #ifdef DEBUG
13893             if (verbose)
13894             {
13895                 printf("\nFolding binary operator with constant nodes into a comma throw:\n");
13896                 gtDispTree(tree);
13897             }
13898 #endif
13899             /* We will change the cast to a GT_COMMA and attach the exception helper as gtOp.gtOp1.
13900              * The constant expression zero becomes op2. */
13901
13902             assert(tree->gtOverflow());
13903             assert(tree->gtOper == GT_ADD || tree->gtOper == GT_SUB || tree->gtOper == GT_CAST ||
13904                    tree->gtOper == GT_MUL);
13905             assert(op1);
13906
13907             op2 = op1;
13908             op1 = gtNewHelperCallNode(CORINFO_HELP_OVERFLOW, TYP_VOID,
13909                                       gtNewArgList(gtNewIconNode(compCurBB->bbTryIndex)));
13910
13911             // op1 is a call to the JIT helper that throws an Overflow exception
13912             // attach the ExcSet for VNF_OverflowExc(Void) to this call
13913
13914             if (vnStore != nullptr)
13915             {
13916                 op1->gtVNPair =
13917                     vnStore->VNPWithExc(ValueNumPair(ValueNumStore::VNForVoid(), ValueNumStore::VNForVoid()),
13918                                         vnStore->VNPExcSetSingleton(
13919                                             vnStore->VNPairForFunc(TYP_REF, VNF_OverflowExc, vnStore->VNPForVoid())));
13920             }
13921
13922             tree = gtNewOperNode(GT_COMMA, tree->gtType, op1, op2);
13923
13924             return tree;
13925
13926         /*-------------------------------------------------------------------------
13927          * Fold constant LONG binary operator
13928          */
13929
13930         case TYP_LONG:
13931
13932             // No GC pointer types should be folded here...
13933             //
13934             assert(!varTypeIsGC(op1->gtType) && !varTypeIsGC(op2->gtType));
13935
13936             // op1 is known to be a TYP_LONG, op2 is normally a TYP_LONG, unless we have a shift operator in which case
13937             // it is a TYP_INT
13938             //
13939             assert((op2->gtType == TYP_LONG) || (op2->gtType == TYP_INT));
13940
13941             if (!op1->gtIntConCommon.ImmedValCanBeFolded(this, tree->OperGet()))
13942             {
13943                 return tree;
13944             }
13945
13946             if (!op2->gtIntConCommon.ImmedValCanBeFolded(this, tree->OperGet()))
13947             {
13948                 return tree;
13949             }
13950
13951             lval1 = op1->gtIntConCommon.LngValue();
13952
13953             // For the shift operators we can have a op2 that is a TYP_INT and thus will be GT_CNS_INT
13954             if (op2->OperGet() == GT_CNS_INT)
13955             {
13956                 lval2 = op2->gtIntConCommon.IconValue();
13957             }
13958             else
13959             {
13960                 lval2 = op2->gtIntConCommon.LngValue();
13961             }
13962
13963             switch (tree->gtOper)
13964             {
13965                 case GT_EQ:
13966                     i1 = (lval1 == lval2);
13967                     goto FOLD_COND;
13968                 case GT_NE:
13969                     i1 = (lval1 != lval2);
13970                     goto FOLD_COND;
13971
13972                 case GT_LT:
13973                     if (tree->gtFlags & GTF_UNSIGNED)
13974                     {
13975                         i1 = (UINT64(lval1) < UINT64(lval2));
13976                     }
13977                     else
13978                     {
13979                         i1 = (lval1 < lval2);
13980                     }
13981                     goto FOLD_COND;
13982
13983                 case GT_LE:
13984                     if (tree->gtFlags & GTF_UNSIGNED)
13985                     {
13986                         i1 = (UINT64(lval1) <= UINT64(lval2));
13987                     }
13988                     else
13989                     {
13990                         i1 = (lval1 <= lval2);
13991                     }
13992                     goto FOLD_COND;
13993
13994                 case GT_GE:
13995                     if (tree->gtFlags & GTF_UNSIGNED)
13996                     {
13997                         i1 = (UINT64(lval1) >= UINT64(lval2));
13998                     }
13999                     else
14000                     {
14001                         i1 = (lval1 >= lval2);
14002                     }
14003                     goto FOLD_COND;
14004
14005                 case GT_GT:
14006                     if (tree->gtFlags & GTF_UNSIGNED)
14007                     {
14008                         i1 = (UINT64(lval1) > UINT64(lval2));
14009                     }
14010                     else
14011                     {
14012                         i1 = (lval1 > lval2);
14013                     }
14014                     goto FOLD_COND;
14015
14016                 case GT_ADD:
14017                     ltemp = lval1 + lval2;
14018
14019                 LNG_ADD_CHKOVF:
14020                     /* For the SIGNED case - If there is one positive and one negative operand, there can be no overflow
14021                      * If both are positive, the result has to be positive, and similary for negatives.
14022                      *
14023                      * For the UNSIGNED case - If a UINT32 operand is bigger than the result then OVF */
14024
14025                     if (tree->gtOverflow())
14026                     {
14027                         if (tree->gtFlags & GTF_UNSIGNED)
14028                         {
14029                             if ((UINT64(lval1) > UINT64(ltemp)) || (UINT64(lval2) > UINT64(ltemp)))
14030                             {
14031                                 goto LNG_OVF;
14032                             }
14033                         }
14034                         else if (((lval1 < 0) == (lval2 < 0)) && ((lval1 < 0) != (ltemp < 0)))
14035                         {
14036                             goto LNG_OVF;
14037                         }
14038                     }
14039                     lval1 = ltemp;
14040                     break;
14041
14042                 case GT_SUB:
14043                     ltemp = lval1 - lval2;
14044                     if (tree->gtOverflow())
14045                     {
14046                         if (tree->gtFlags & GTF_UNSIGNED)
14047                         {
14048                             if (UINT64(lval2) > UINT64(lval1))
14049                             {
14050                                 goto LNG_OVF;
14051                             }
14052                         }
14053                         else
14054                         {
14055                             /* If both operands are +ve or both are -ve, there can be no
14056                                overflow. Else use the logic for : lval1 + (-lval2) */
14057
14058                             if ((lval1 < 0) != (lval2 < 0))
14059                             {
14060                                 if (lval2 == INT64_MIN)
14061                                 {
14062                                     goto LNG_OVF;
14063                                 }
14064                                 lval2 = -lval2;
14065                                 goto LNG_ADD_CHKOVF;
14066                             }
14067                         }
14068                     }
14069                     lval1 = ltemp;
14070                     break;
14071
14072                 case GT_MUL:
14073                     ltemp = lval1 * lval2;
14074
14075                     if (tree->gtOverflow() && lval2 != 0)
14076                     {
14077
14078                         if (tree->gtFlags & GTF_UNSIGNED)
14079                         {
14080                             UINT64 ultemp = ltemp;
14081                             UINT64 ulval1 = lval1;
14082                             UINT64 ulval2 = lval2;
14083                             if ((ultemp / ulval2) != ulval1)
14084                             {
14085                                 goto LNG_OVF;
14086                             }
14087                         }
14088                         else
14089                         {
14090                             // This does a multiply and then reverses it.  This test works great except for MIN_INT *
14091                             //-1.  In that case we mess up the sign on ltmp.  Make sure to double check the sign.
14092                             // if either is 0, then no overflow
14093                             if (lval1 != 0) // lval2 checked above.
14094                             {
14095                                 if (((lval1 < 0) == (lval2 < 0)) && (ltemp < 0))
14096                                 {
14097                                     goto LNG_OVF;
14098                                 }
14099                                 if (((lval1 < 0) != (lval2 < 0)) && (ltemp > 0))
14100                                 {
14101                                     goto LNG_OVF;
14102                                 }
14103
14104                                 // TODO-Amd64-Unix: Remove the code that disables optimizations for this method when the
14105                                 // clang
14106                                 // optimizer is fixed and/or the method implementation is refactored in a simpler code.
14107                                 // There is a bug in the clang-3.5 optimizer. The issue is that in release build the
14108                                 // optimizer is mistyping (or just wrongly decides to use 32 bit operation for a corner
14109                                 // case of MIN_LONG) the args of the (ltemp / lval2) to int (it does a 32 bit div
14110                                 // operation instead of 64 bit.). For the case of lval1 and lval2 equal to MIN_LONG
14111                                 // (0x8000000000000000) this results in raising a SIGFPE.
14112                                 // Optimizations disabled for now. See compiler.h.
14113                                 if ((ltemp / lval2) != lval1)
14114                                 {
14115                                     goto LNG_OVF;
14116                                 }
14117                             }
14118                         }
14119                     }
14120
14121                     lval1 = ltemp;
14122                     break;
14123
14124                 case GT_OR:
14125                     lval1 |= lval2;
14126                     break;
14127                 case GT_XOR:
14128                     lval1 ^= lval2;
14129                     break;
14130                 case GT_AND:
14131                     lval1 &= lval2;
14132                     break;
14133
14134                 case GT_LSH:
14135                     lval1 <<= (lval2 & 0x3f);
14136                     break;
14137                 case GT_RSH:
14138                     lval1 >>= (lval2 & 0x3f);
14139                     break;
14140                 case GT_RSZ:
14141                     /* logical shift -> make it unsigned to not propagate the sign bit */
14142                     lval1 = UINT64(lval1) >> (lval2 & 0x3f);
14143                     break;
14144                 case GT_ROL:
14145                     lval1 = (lval1 << (lval2 & 0x3f)) | (UINT64(lval1) >> ((64 - lval2) & 0x3f));
14146                     break;
14147                 case GT_ROR:
14148                     lval1 = (lval1 << ((64 - lval2) & 0x3f)) | (UINT64(lval1) >> (lval2 & 0x3f));
14149                     break;
14150
14151                 // Both DIV and IDIV on x86 raise an exception for min_int (and min_long) / -1.  So we preserve
14152                 // that behavior here.
14153                 case GT_DIV:
14154                     if (!lval2)
14155                     {
14156                         return tree;
14157                     }
14158
14159                     if (UINT64(lval1) == UI64(0x8000000000000000) && lval2 == INT64(-1))
14160                     {
14161                         return tree;
14162                     }
14163                     lval1 /= lval2;
14164                     break;
14165
14166                 case GT_MOD:
14167                     if (!lval2)
14168                     {
14169                         return tree;
14170                     }
14171                     if (UINT64(lval1) == UI64(0x8000000000000000) && lval2 == INT64(-1))
14172                     {
14173                         return tree;
14174                     }
14175                     lval1 %= lval2;
14176                     break;
14177
14178                 case GT_UDIV:
14179                     if (!lval2)
14180                     {
14181                         return tree;
14182                     }
14183                     if (UINT64(lval1) == UI64(0x8000000000000000) && lval2 == INT64(-1))
14184                     {
14185                         return tree;
14186                     }
14187                     lval1 = UINT64(lval1) / UINT64(lval2);
14188                     break;
14189
14190                 case GT_UMOD:
14191                     if (!lval2)
14192                     {
14193                         return tree;
14194                     }
14195                     if (UINT64(lval1) == UI64(0x8000000000000000) && lval2 == INT64(-1))
14196                     {
14197                         return tree;
14198                     }
14199                     lval1 = UINT64(lval1) % UINT64(lval2);
14200                     break;
14201                 default:
14202                     return tree;
14203             }
14204
14205         CNS_LONG:
14206
14207             if (fieldSeq != FieldSeqStore::NotAField())
14208             {
14209                 return tree;
14210             }
14211
14212 #ifdef DEBUG
14213             if (verbose)
14214             {
14215                 printf("\nFolding long operator with constant nodes into a constant:\n");
14216                 gtDispTree(tree);
14217             }
14218 #endif
14219             assert((GenTree::s_gtNodeSizes[GT_CNS_NATIVELONG] == TREE_NODE_SZ_SMALL) ||
14220                    (tree->gtDebugFlags & GTF_DEBUG_NODE_LARGE));
14221
14222             tree->ChangeOperConst(GT_CNS_NATIVELONG);
14223             tree->gtIntConCommon.SetLngValue(lval1);
14224             if (vnStore != nullptr)
14225             {
14226                 fgValueNumberTreeConst(tree);
14227             }
14228
14229 #ifdef DEBUG
14230             if (verbose)
14231             {
14232                 printf("Bashed to long constant:\n");
14233                 gtDispTree(tree);
14234             }
14235 #endif
14236             goto DONE;
14237
14238         /*-------------------------------------------------------------------------
14239          * Fold constant FLOAT or DOUBLE binary operator
14240          */
14241
14242         case TYP_FLOAT:
14243         case TYP_DOUBLE:
14244
14245             if (tree->gtOverflowEx())
14246             {
14247                 return tree;
14248             }
14249
14250             assert(op1->gtOper == GT_CNS_DBL);
14251             d1 = op1->gtDblCon.gtDconVal;
14252
14253             assert(varTypeIsFloating(op2->gtType));
14254             assert(op2->gtOper == GT_CNS_DBL);
14255             d2 = op2->gtDblCon.gtDconVal;
14256
14257             /* Special case - check if we have NaN operands.
14258              * For comparisons if not an unordered operation always return 0.
14259              * For unordered operations (i.e. the GTF_RELOP_NAN_UN flag is set)
14260              * the result is always true - return 1. */
14261
14262             if (_isnan(d1) || _isnan(d2))
14263             {
14264 #ifdef DEBUG
14265                 if (verbose)
14266                 {
14267                     printf("Double operator(s) is NaN\n");
14268                 }
14269 #endif
14270                 if (tree->OperKind() & GTK_RELOP)
14271                 {
14272                     if (tree->gtFlags & GTF_RELOP_NAN_UN)
14273                     {
14274                         /* Unordered comparison with NaN always succeeds */
14275                         i1 = 1;
14276                         goto FOLD_COND;
14277                     }
14278                     else
14279                     {
14280                         /* Normal comparison with NaN always fails */
14281                         i1 = 0;
14282                         goto FOLD_COND;
14283                     }
14284                 }
14285             }
14286
14287             switch (tree->gtOper)
14288             {
14289                 case GT_EQ:
14290                     i1 = (d1 == d2);
14291                     goto FOLD_COND;
14292                 case GT_NE:
14293                     i1 = (d1 != d2);
14294                     goto FOLD_COND;
14295
14296                 case GT_LT:
14297                     i1 = (d1 < d2);
14298                     goto FOLD_COND;
14299                 case GT_LE:
14300                     i1 = (d1 <= d2);
14301                     goto FOLD_COND;
14302                 case GT_GE:
14303                     i1 = (d1 >= d2);
14304                     goto FOLD_COND;
14305                 case GT_GT:
14306                     i1 = (d1 > d2);
14307                     goto FOLD_COND;
14308
14309                 // Floating point arithmetic should be done in declared
14310                 // precision while doing constant folding. For this reason though TYP_FLOAT
14311                 // constants are stored as double constants, while performing float arithmetic,
14312                 // double constants should be converted to float.  Here is an example case
14313                 // where performing arithmetic in double precision would lead to incorrect
14314                 // results.
14315                 //
14316                 // Example:
14317                 // float a = float.MaxValue;
14318                 // float b = a*a;   This will produce +inf in single precision and 1.1579207543382391e+077 in double
14319                 //                  precision.
14320                 // flaot c = b/b;   This will produce NaN in single precision and 1 in double precision.
14321                 case GT_ADD:
14322                     if (op1->TypeGet() == TYP_FLOAT)
14323                     {
14324                         f1 = forceCastToFloat(d1);
14325                         f2 = forceCastToFloat(d2);
14326                         d1 = forceCastToFloat(f1 + f2);
14327                     }
14328                     else
14329                     {
14330                         d1 += d2;
14331                     }
14332                     break;
14333
14334                 case GT_SUB:
14335                     if (op1->TypeGet() == TYP_FLOAT)
14336                     {
14337                         f1 = forceCastToFloat(d1);
14338                         f2 = forceCastToFloat(d2);
14339                         d1 = forceCastToFloat(f1 - f2);
14340                     }
14341                     else
14342                     {
14343                         d1 -= d2;
14344                     }
14345                     break;
14346
14347                 case GT_MUL:
14348                     if (op1->TypeGet() == TYP_FLOAT)
14349                     {
14350                         f1 = forceCastToFloat(d1);
14351                         f2 = forceCastToFloat(d2);
14352                         d1 = forceCastToFloat(f1 * f2);
14353                     }
14354                     else
14355                     {
14356                         d1 *= d2;
14357                     }
14358                     break;
14359
14360                 case GT_DIV:
14361                     if (!d2)
14362                     {
14363                         return tree;
14364                     }
14365                     if (op1->TypeGet() == TYP_FLOAT)
14366                     {
14367                         f1 = forceCastToFloat(d1);
14368                         f2 = forceCastToFloat(d2);
14369                         d1 = forceCastToFloat(f1 / f2);
14370                     }
14371                     else
14372                     {
14373                         d1 /= d2;
14374                     }
14375                     break;
14376
14377                 default:
14378                     return tree;
14379             }
14380
14381         CNS_DOUBLE:
14382
14383 #ifdef DEBUG
14384             if (verbose)
14385             {
14386                 printf("\nFolding fp operator with constant nodes into a fp constant:\n");
14387                 gtDispTree(tree);
14388             }
14389 #endif
14390
14391             assert((GenTree::s_gtNodeSizes[GT_CNS_DBL] == TREE_NODE_SZ_SMALL) ||
14392                    (tree->gtDebugFlags & GTF_DEBUG_NODE_LARGE));
14393
14394             tree->ChangeOperConst(GT_CNS_DBL);
14395             tree->gtDblCon.gtDconVal = d1;
14396             if (vnStore != nullptr)
14397             {
14398                 fgValueNumberTreeConst(tree);
14399             }
14400 #ifdef DEBUG
14401             if (verbose)
14402             {
14403                 printf("Bashed to fp constant:\n");
14404                 gtDispTree(tree);
14405             }
14406 #endif
14407             goto DONE;
14408
14409         default:
14410             /* not a foldable typ */
14411             return tree;
14412     }
14413
14414 //-------------------------------------------------------------------------
14415
14416 DONE:
14417
14418     /* Make sure no side effect flags are set on this constant node */
14419
14420     tree->gtFlags &= ~GTF_ALL_EFFECT;
14421
14422     return tree;
14423 }
14424 #ifdef _PREFAST_
14425 #pragma warning(pop)
14426 #endif
14427
14428 //------------------------------------------------------------------------
14429 // gtNewTempAssign: Create an assignment of the given value to a temp.
14430 //
14431 // Arguments:
14432 //    tmp         - local number for a compiler temp
14433 //    val         - value to assign to the temp
14434 //    pAfterStmt  - statement to insert any additional statements after
14435 //    ilOffset    - il offset for new statements
14436 //    block       - block to insert any additional statements in
14437 //
14438 // Return Value:
14439 //    Normally a new assignment node.
14440 //    However may return a nop node if val is simply a reference to the temp.
14441 //
14442 // Notes:
14443 //    Self-assignments may be represented via NOPs.
14444 //
14445 //    May update the type of the temp, if it was previously unknown.
14446 //
14447 //    May set compFloatingPointUsed.
14448
14449 GenTree* Compiler::gtNewTempAssign(
14450     unsigned tmp, GenTree* val, GenTree** pAfterStmt, IL_OFFSETX ilOffset, BasicBlock* block)
14451 {
14452     // Self-assignment is a nop.
14453     if (val->OperGet() == GT_LCL_VAR && val->gtLclVarCommon.gtLclNum == tmp)
14454     {
14455         return gtNewNothingNode();
14456     }
14457
14458     LclVarDsc* varDsc = lvaTable + tmp;
14459
14460     if (varDsc->TypeGet() == TYP_I_IMPL && val->TypeGet() == TYP_BYREF)
14461     {
14462         impBashVarAddrsToI(val);
14463     }
14464
14465     var_types valTyp = val->TypeGet();
14466     if (val->OperGet() == GT_LCL_VAR && lvaTable[val->gtLclVar.gtLclNum].lvNormalizeOnLoad())
14467     {
14468         valTyp      = lvaGetRealType(val->gtLclVar.gtLclNum);
14469         val->gtType = valTyp;
14470     }
14471     var_types dstTyp = varDsc->TypeGet();
14472
14473     /* If the variable's lvType is not yet set then set it here */
14474     if (dstTyp == TYP_UNDEF)
14475     {
14476         varDsc->lvType = dstTyp = genActualType(valTyp);
14477         if (varTypeIsGC(dstTyp))
14478         {
14479             varDsc->lvStructGcCount = 1;
14480         }
14481 #if FEATURE_SIMD
14482         else if (varTypeIsSIMD(dstTyp))
14483         {
14484             varDsc->lvSIMDType = 1;
14485         }
14486 #endif
14487     }
14488
14489 #ifdef DEBUG
14490     /* Make sure the actual types match               */
14491     if (genActualType(valTyp) != genActualType(dstTyp))
14492     {
14493         // Plus some other exceptions that are apparently legal:
14494         // 1) TYP_REF or BYREF = TYP_I_IMPL
14495         bool ok = false;
14496         if (varTypeIsGC(dstTyp) && (valTyp == TYP_I_IMPL))
14497         {
14498             ok = true;
14499         }
14500         // 2) TYP_DOUBLE = TYP_FLOAT or TYP_FLOAT = TYP_DOUBLE
14501         else if (varTypeIsFloating(dstTyp) && varTypeIsFloating(valTyp))
14502         {
14503             ok = true;
14504         }
14505
14506         if (!ok)
14507         {
14508             gtDispTree(val);
14509             assert(!"Incompatible types for gtNewTempAssign");
14510         }
14511     }
14512 #endif
14513
14514     // Floating Point assignments can be created during inlining
14515     // see "Zero init inlinee locals:" in fgInlinePrependStatements
14516     // thus we may need to set compFloatingPointUsed to true here.
14517     //
14518     if (varTypeIsFloating(dstTyp) && (compFloatingPointUsed == false))
14519     {
14520         compFloatingPointUsed = true;
14521     }
14522
14523     /* Create the assignment node */
14524
14525     GenTree* asg;
14526     GenTree* dest = gtNewLclvNode(tmp, dstTyp);
14527     dest->gtFlags |= GTF_VAR_DEF;
14528
14529     // With first-class structs, we should be propagating the class handle on all non-primitive
14530     // struct types. We don't have a convenient way to do that for all SIMD temps, since some
14531     // internal trees use SIMD types that are not used by the input IL. In this case, we allow
14532     // a null type handle and derive the necessary information about the type from its varType.
14533     CORINFO_CLASS_HANDLE structHnd = gtGetStructHandleIfPresent(val);
14534     if (varTypeIsStruct(valTyp) && ((structHnd != NO_CLASS_HANDLE) || (varTypeIsSIMD(valTyp))))
14535     {
14536         // The struct value may be be a child of a GT_COMMA.
14537         GenTree* valx = val->gtEffectiveVal(/*commaOnly*/ true);
14538
14539         if (structHnd != NO_CLASS_HANDLE)
14540         {
14541             lvaSetStruct(tmp, structHnd, false);
14542         }
14543         else
14544         {
14545             assert(valx->gtOper != GT_OBJ);
14546         }
14547         dest->gtFlags |= GTF_DONT_CSE;
14548         valx->gtFlags |= GTF_DONT_CSE;
14549         asg = impAssignStruct(dest, val, structHnd, (unsigned)CHECK_SPILL_NONE, pAfterStmt, ilOffset, block);
14550     }
14551     else
14552     {
14553         asg = gtNewAssignNode(dest, val);
14554     }
14555
14556     if (compRationalIRForm)
14557     {
14558         Rationalizer::RewriteAssignmentIntoStoreLcl(asg->AsOp());
14559     }
14560
14561     return asg;
14562 }
14563
14564 /*****************************************************************************
14565  *
14566  *  Create a helper call to access a COM field (iff 'assg' is non-zero this is
14567  *  an assignment and 'assg' is the new value).
14568  */
14569
14570 GenTree* Compiler::gtNewRefCOMfield(GenTree*                objPtr,
14571                                     CORINFO_RESOLVED_TOKEN* pResolvedToken,
14572                                     CORINFO_ACCESS_FLAGS    access,
14573                                     CORINFO_FIELD_INFO*     pFieldInfo,
14574                                     var_types               lclTyp,
14575                                     CORINFO_CLASS_HANDLE    structType,
14576                                     GenTree*                assg)
14577 {
14578     assert(pFieldInfo->fieldAccessor == CORINFO_FIELD_INSTANCE_HELPER ||
14579            pFieldInfo->fieldAccessor == CORINFO_FIELD_INSTANCE_ADDR_HELPER ||
14580            pFieldInfo->fieldAccessor == CORINFO_FIELD_STATIC_ADDR_HELPER);
14581
14582     /* If we can't access it directly, we need to call a helper function */
14583     GenTreeArgList* args       = nullptr;
14584     var_types       helperType = TYP_BYREF;
14585
14586     if (pFieldInfo->fieldAccessor == CORINFO_FIELD_INSTANCE_HELPER)
14587     {
14588         if (access & CORINFO_ACCESS_SET)
14589         {
14590             assert(assg != nullptr);
14591             // helper needs pointer to struct, not struct itself
14592             if (pFieldInfo->helper == CORINFO_HELP_SETFIELDSTRUCT)
14593             {
14594                 assert(structType != nullptr);
14595                 assg = impGetStructAddr(assg, structType, (unsigned)CHECK_SPILL_ALL, true);
14596             }
14597             else if (lclTyp == TYP_DOUBLE && assg->TypeGet() == TYP_FLOAT)
14598             {
14599                 assg = gtNewCastNode(TYP_DOUBLE, assg, false, TYP_DOUBLE);
14600             }
14601             else if (lclTyp == TYP_FLOAT && assg->TypeGet() == TYP_DOUBLE)
14602             {
14603                 assg = gtNewCastNode(TYP_FLOAT, assg, false, TYP_FLOAT);
14604             }
14605
14606             args       = gtNewArgList(assg);
14607             helperType = TYP_VOID;
14608         }
14609         else if (access & CORINFO_ACCESS_GET)
14610         {
14611             helperType = lclTyp;
14612
14613             // The calling convention for the helper does not take into
14614             // account optimization of primitive structs.
14615             if ((pFieldInfo->helper == CORINFO_HELP_GETFIELDSTRUCT) && !varTypeIsStruct(lclTyp))
14616             {
14617                 helperType = TYP_STRUCT;
14618             }
14619         }
14620     }
14621
14622     if (pFieldInfo->helper == CORINFO_HELP_GETFIELDSTRUCT || pFieldInfo->helper == CORINFO_HELP_SETFIELDSTRUCT)
14623     {
14624         assert(pFieldInfo->structType != nullptr);
14625         args = gtNewListNode(gtNewIconEmbClsHndNode(pFieldInfo->structType), args);
14626     }
14627
14628     GenTree* fieldHnd = impTokenToHandle(pResolvedToken);
14629     if (fieldHnd == nullptr)
14630     { // compDonotInline()
14631         return nullptr;
14632     }
14633
14634     args = gtNewListNode(fieldHnd, args);
14635
14636     // If it's a static field, we shouldn't have an object node
14637     // If it's an instance field, we have an object node
14638     assert((pFieldInfo->fieldAccessor != CORINFO_FIELD_STATIC_ADDR_HELPER) ^ (objPtr == nullptr));
14639
14640     if (objPtr != nullptr)
14641     {
14642         args = gtNewListNode(objPtr, args);
14643     }
14644
14645     GenTreeCall* call = gtNewHelperCallNode(pFieldInfo->helper, genActualType(helperType), args);
14646
14647 #if FEATURE_MULTIREG_RET
14648     if (varTypeIsStruct(call))
14649     {
14650         // Initialize Return type descriptor of call node.
14651         ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc();
14652         retTypeDesc->InitializeStructReturnType(this, structType);
14653     }
14654 #endif // FEATURE_MULTIREG_RET
14655
14656     GenTree* result = call;
14657
14658     if (pFieldInfo->fieldAccessor == CORINFO_FIELD_INSTANCE_HELPER)
14659     {
14660         if (access & CORINFO_ACCESS_GET)
14661         {
14662             if (pFieldInfo->helper == CORINFO_HELP_GETFIELDSTRUCT)
14663             {
14664                 if (!varTypeIsStruct(lclTyp))
14665                 {
14666                     // get the result as primitive type
14667                     result = impGetStructAddr(result, structType, (unsigned)CHECK_SPILL_ALL, true);
14668                     result = gtNewOperNode(GT_IND, lclTyp, result);
14669                 }
14670             }
14671             else if (varTypeIsIntegral(lclTyp) && genTypeSize(lclTyp) < genTypeSize(TYP_INT))
14672             {
14673                 // The helper does not extend the small return types.
14674                 result = gtNewCastNode(genActualType(lclTyp), result, false, lclTyp);
14675             }
14676         }
14677     }
14678     else
14679     {
14680         // OK, now do the indirection
14681         if (access & CORINFO_ACCESS_GET)
14682         {
14683             if (varTypeIsStruct(lclTyp))
14684             {
14685                 result = gtNewObjNode(structType, result);
14686             }
14687             else
14688             {
14689                 result = gtNewOperNode(GT_IND, lclTyp, result);
14690             }
14691             result->gtFlags |= (GTF_EXCEPT | GTF_GLOB_REF);
14692         }
14693         else if (access & CORINFO_ACCESS_SET)
14694         {
14695             if (varTypeIsStruct(lclTyp))
14696             {
14697                 result = impAssignStructPtr(result, assg, structType, (unsigned)CHECK_SPILL_ALL);
14698             }
14699             else
14700             {
14701                 result = gtNewOperNode(GT_IND, lclTyp, result);
14702                 result->gtFlags |= (GTF_EXCEPT | GTF_GLOB_REF | GTF_IND_TGTANYWHERE);
14703                 result = gtNewAssignNode(result, assg);
14704             }
14705         }
14706     }
14707
14708     return result;
14709 }
14710
14711 /*****************************************************************************
14712  *
14713  *  Return true if the given node (excluding children trees) contains side effects.
14714  *  Note that it does not recurse, and children need to be handled separately.
14715  *  It may return false even if the node has GTF_SIDE_EFFECT (because of its children).
14716  *
14717  *  Similar to OperMayThrow() (but handles GT_CALLs specially), but considers
14718  *  assignments too.
14719  */
14720
14721 bool Compiler::gtNodeHasSideEffects(GenTree* tree, unsigned flags)
14722 {
14723     if (flags & GTF_ASG)
14724     {
14725         // TODO-Cleanup: This only checks for GT_ASG but according to OperRequiresAsgFlag there
14726         // are many more opers that are considered to have an assignment side effect: atomic ops
14727         // (GT_CMPXCHG & co.), GT_MEMORYBARRIER (not classified as an atomic op) and HW intrinsic
14728         // memory stores. Atomic ops have special handling in gtExtractSideEffList but the others
14729         // will simply be dropped is they are ever subject to an "extract side effects" operation.
14730         // It is possible that the reason no bugs have yet been observed in this area is that the
14731         // other nodes are likely to always be tree roots.
14732         if (tree->OperIs(GT_ASG))
14733         {
14734             return true;
14735         }
14736     }
14737
14738     // Are there only GTF_CALL side effects remaining? (and no other side effect kinds)
14739     if (flags & GTF_CALL)
14740     {
14741         if (tree->OperGet() == GT_CALL)
14742         {
14743             GenTreeCall* const call             = tree->AsCall();
14744             const bool         ignoreExceptions = (flags & GTF_EXCEPT) == 0;
14745             const bool         ignoreCctors     = (flags & GTF_IS_IN_CSE) != 0; // We can CSE helpers that run cctors.
14746             if (!call->HasSideEffects(this, ignoreExceptions, ignoreCctors))
14747             {
14748                 // If this call is otherwise side effect free, check its arguments.
14749                 for (GenTreeArgList* args = call->gtCallArgs; args != nullptr; args = args->Rest())
14750                 {
14751                     if (gtTreeHasSideEffects(args->Current(), flags))
14752                     {
14753                         return true;
14754                     }
14755                 }
14756                 // I'm a little worried that args that assign to temps that are late args will look like
14757                 // side effects...but better to be conservative for now.
14758                 for (GenTreeArgList* args = call->gtCallLateArgs; args != nullptr; args = args->Rest())
14759                 {
14760                     if (gtTreeHasSideEffects(args->Current(), flags))
14761                     {
14762                         return true;
14763                     }
14764                 }
14765
14766                 // Otherwise:
14767                 return false;
14768             }
14769
14770             // Otherwise the GT_CALL is considered to have side-effects.
14771             return true;
14772         }
14773     }
14774
14775     if (flags & GTF_EXCEPT)
14776     {
14777         if (tree->OperMayThrow(this))
14778         {
14779             return true;
14780         }
14781     }
14782
14783     // Expressions declared as CSE by (e.g.) hoisting code are considered to have relevant side
14784     // effects (if we care about GTF_MAKE_CSE).
14785     if ((flags & GTF_MAKE_CSE) && (tree->gtFlags & GTF_MAKE_CSE))
14786     {
14787         return true;
14788     }
14789
14790     return false;
14791 }
14792
14793 /*****************************************************************************
14794  * Returns true if the expr tree has any side effects.
14795  */
14796
14797 bool Compiler::gtTreeHasSideEffects(GenTree* tree, unsigned flags /* = GTF_SIDE_EFFECT*/)
14798 {
14799     // These are the side effect flags that we care about for this tree
14800     unsigned sideEffectFlags = tree->gtFlags & flags;
14801
14802     // Does this tree have any Side-effect flags set that we care about?
14803     if (sideEffectFlags == 0)
14804     {
14805         // no it doesn't..
14806         return false;
14807     }
14808
14809     if (sideEffectFlags == GTF_CALL)
14810     {
14811         if (tree->OperGet() == GT_CALL)
14812         {
14813             // Generally all trees that contain GT_CALL nodes are considered to have side-effects.
14814             //
14815             if (tree->gtCall.gtCallType == CT_HELPER)
14816             {
14817                 // If this node is a helper call we may not care about the side-effects.
14818                 // Note that gtNodeHasSideEffects checks the side effects of the helper itself
14819                 // as well as the side effects of its arguments.
14820                 return gtNodeHasSideEffects(tree, flags);
14821             }
14822         }
14823         else if (tree->OperGet() == GT_INTRINSIC)
14824         {
14825             if (gtNodeHasSideEffects(tree, flags))
14826             {
14827                 return true;
14828             }
14829
14830             if (gtNodeHasSideEffects(tree->gtOp.gtOp1, flags))
14831             {
14832                 return true;
14833             }
14834
14835             if ((tree->gtOp.gtOp2 != nullptr) && gtNodeHasSideEffects(tree->gtOp.gtOp2, flags))
14836             {
14837                 return true;
14838             }
14839
14840             return false;
14841         }
14842     }
14843
14844     return true;
14845 }
14846
14847 GenTree* Compiler::gtBuildCommaList(GenTree* list, GenTree* expr)
14848 {
14849     // 'list' starts off as null,
14850     //        and when it is null we haven't started the list yet.
14851     //
14852     if (list != nullptr)
14853     {
14854         // Create a GT_COMMA that appends 'expr' in front of the remaining set of expressions in (*list)
14855         GenTree* result = gtNewOperNode(GT_COMMA, TYP_VOID, expr, list);
14856
14857         // Set the flags in the comma node
14858         result->gtFlags |= (list->gtFlags & GTF_ALL_EFFECT);
14859         result->gtFlags |= (expr->gtFlags & GTF_ALL_EFFECT);
14860
14861         // 'list' and 'expr' should have valuenumbers defined for both or for neither one (unless we are remorphing,
14862         // in which case a prior transform involving either node may have discarded or otherwise invalidated the value
14863         // numbers).
14864         assert((list->gtVNPair.BothDefined() == expr->gtVNPair.BothDefined()) || !fgGlobalMorph);
14865
14866         // Set the ValueNumber 'gtVNPair' for the new GT_COMMA node
14867         //
14868         if (list->gtVNPair.BothDefined() && expr->gtVNPair.BothDefined())
14869         {
14870             // The result of a GT_COMMA node is op2, the normal value number is op2vnp
14871             // But we also need to include the union of side effects from op1 and op2.
14872             // we compute this value into exceptions_vnp.
14873             ValueNumPair op1vnp;
14874             ValueNumPair op1Xvnp = ValueNumStore::VNPForEmptyExcSet();
14875             ValueNumPair op2vnp;
14876             ValueNumPair op2Xvnp = ValueNumStore::VNPForEmptyExcSet();
14877
14878             vnStore->VNPUnpackExc(expr->gtVNPair, &op1vnp, &op1Xvnp);
14879             vnStore->VNPUnpackExc(list->gtVNPair, &op2vnp, &op2Xvnp);
14880
14881             ValueNumPair exceptions_vnp = ValueNumStore::VNPForEmptyExcSet();
14882
14883             exceptions_vnp = vnStore->VNPExcSetUnion(exceptions_vnp, op1Xvnp);
14884             exceptions_vnp = vnStore->VNPExcSetUnion(exceptions_vnp, op2Xvnp);
14885
14886             result->gtVNPair = vnStore->VNPWithExc(op2vnp, exceptions_vnp);
14887         }
14888
14889         return result;
14890     }
14891     else
14892     {
14893         // The 'expr' will start the list of expressions
14894         return expr;
14895     }
14896 }
14897
14898 //------------------------------------------------------------------------
14899 // gtExtractSideEffList: Extracts side effects from the given expression.
14900 //
14901 // Arguments:
14902 //    expr       - the expression tree to extract side effects from
14903 //    pList      - pointer to a (possibly null) GT_COMMA list that
14904 //                 will contain the extracted side effects
14905 //    flags      - side effect flags to be considered
14906 //    ignoreRoot - ignore side effects on the expression root node
14907 //
14908 // Notes:
14909 //    Side effects are prepended to the GT_COMMA list such that op1 of
14910 //    each comma node holds the side effect tree and op2 points to the
14911 //    next comma node. The original side effect execution order is preserved.
14912 //
14913 void Compiler::gtExtractSideEffList(GenTree*  expr,
14914                                     GenTree** pList,
14915                                     unsigned  flags /* = GTF_SIDE_EFFECT*/,
14916                                     bool      ignoreRoot /* = false */)
14917 {
14918     class SideEffectExtractor final : public GenTreeVisitor<SideEffectExtractor>
14919     {
14920     public:
14921         const unsigned       m_flags;
14922         ArrayStack<GenTree*> m_sideEffects;
14923
14924         enum
14925         {
14926             DoPreOrder        = true,
14927             UseExecutionOrder = true
14928         };
14929
14930         SideEffectExtractor(Compiler* compiler, unsigned flags)
14931             : GenTreeVisitor(compiler), m_flags(flags), m_sideEffects(compiler->getAllocator(CMK_SideEffects))
14932         {
14933         }
14934
14935         fgWalkResult PreOrderVisit(GenTree** use, GenTree* user)
14936         {
14937             GenTree* node = *use;
14938
14939             bool treeHasSideEffects = m_compiler->gtTreeHasSideEffects(node, m_flags);
14940
14941             if (treeHasSideEffects)
14942             {
14943                 if (m_compiler->gtNodeHasSideEffects(node, m_flags))
14944                 {
14945                     m_sideEffects.Push(node);
14946                     return Compiler::WALK_SKIP_SUBTREES;
14947                 }
14948
14949                 // TODO-Cleanup: These have GTF_ASG set but for some reason gtNodeHasSideEffects ignores
14950                 // them. See the related gtNodeHasSideEffects comment as well.
14951                 // Also, these nodes must always be preserved, no matter what side effect flags are passed
14952                 // in. But then it should never be the case that gtExtractSideEffList gets called without
14953                 // specifying GTF_ASG so there doesn't seem to be any reason to be inconsistent with
14954                 // gtNodeHasSideEffects and make this check unconditionally.
14955                 if (node->OperIsAtomicOp())
14956                 {
14957                     m_sideEffects.Push(node);
14958                     return Compiler::WALK_SKIP_SUBTREES;
14959                 }
14960
14961                 if ((m_flags & GTF_EXCEPT) != 0)
14962                 {
14963                     // Special case - GT_ADDR of GT_IND nodes of TYP_STRUCT have to be kept together.
14964                     if (node->OperIs(GT_ADDR) && node->gtGetOp1()->OperIsIndir() &&
14965                         (node->gtGetOp1()->TypeGet() == TYP_STRUCT))
14966                     {
14967 #ifdef DEBUG
14968                         if (m_compiler->verbose)
14969                         {
14970                             printf("Keep the GT_ADDR and GT_IND together:\n");
14971                         }
14972 #endif
14973                         m_sideEffects.Push(node);
14974                         return Compiler::WALK_SKIP_SUBTREES;
14975                     }
14976                 }
14977
14978                 // Generally all GT_CALL nodes are considered to have side-effects.
14979                 // So if we get here it must be a helper call that we decided it does
14980                 // not have side effects that we needed to keep.
14981                 assert(!node->OperIs(GT_CALL) || (node->AsCall()->gtCallType == CT_HELPER));
14982             }
14983
14984             if ((m_flags & GTF_IS_IN_CSE) != 0)
14985             {
14986                 // If we're doing CSE then we also need to unmark CSE nodes. This will fail for CSE defs,
14987                 // those need to be extracted as if they're side effects.
14988                 if (!UnmarkCSE(node))
14989                 {
14990                     m_sideEffects.Push(node);
14991                     return Compiler::WALK_SKIP_SUBTREES;
14992                 }
14993
14994                 // The existence of CSE defs and uses is not propagated up the tree like side
14995                 // effects are. We need to continue visiting the tree as if it has side effects.
14996                 treeHasSideEffects = true;
14997             }
14998
14999             return treeHasSideEffects ? Compiler::WALK_CONTINUE : Compiler::WALK_SKIP_SUBTREES;
15000         }
15001
15002     private:
15003         bool UnmarkCSE(GenTree* node)
15004         {
15005             assert(m_compiler->optValnumCSE_phase);
15006
15007             if (m_compiler->optUnmarkCSE(node))
15008             {
15009                 // The call to optUnmarkCSE(node) should have cleared any CSE info.
15010                 assert(!IS_CSE_INDEX(node->gtCSEnum));
15011                 return true;
15012             }
15013             else
15014             {
15015                 assert(IS_CSE_DEF(node->gtCSEnum));
15016 #ifdef DEBUG
15017                 if (m_compiler->verbose)
15018                 {
15019                     printf("Preserving the CSE def #%02d at ", GET_CSE_INDEX(node->gtCSEnum));
15020                     m_compiler->printTreeID(node);
15021                 }
15022 #endif
15023                 return false;
15024             }
15025         }
15026     };
15027
15028     assert(!expr->OperIs(GT_STMT));
15029
15030     SideEffectExtractor extractor(this, flags);
15031
15032     if (ignoreRoot)
15033     {
15034         for (GenTree* op : expr->Operands())
15035         {
15036             extractor.WalkTree(&op, nullptr);
15037         }
15038     }
15039     else
15040     {
15041         extractor.WalkTree(&expr, nullptr);
15042     }
15043
15044     GenTree* list = *pList;
15045
15046     // The extractor returns side effects in execution order but gtBuildCommaList prepends
15047     // to the comma-based side effect list so we have to build the list in reverse order.
15048     // This is also why the list cannot be built while traversing the tree.
15049     // The number of side effects is usually small (<= 4), less than the ArrayStack's
15050     // built-in size, so memory allocation is avoided.
15051     while (extractor.m_sideEffects.Height() > 0)
15052     {
15053         list = gtBuildCommaList(list, extractor.m_sideEffects.Pop());
15054     }
15055
15056     *pList = list;
15057 }
15058
15059 /*****************************************************************************
15060  *
15061  *  For debugging only - displays a tree node list and makes sure all the
15062  *  links are correctly set.
15063  */
15064
15065 #ifdef DEBUG
15066
15067 void dispNodeList(GenTree* list, bool verbose)
15068 {
15069     GenTree* last = nullptr;
15070     GenTree* next;
15071
15072     if (!list)
15073     {
15074         return;
15075     }
15076
15077     for (;;)
15078     {
15079         next = list->gtNext;
15080
15081         if (verbose)
15082         {
15083             printf("%08X -> %08X -> %08X\n", last, list, next);
15084         }
15085
15086         assert(!last || last->gtNext == list);
15087
15088         assert(next == nullptr || next->gtPrev == list);
15089
15090         if (!next)
15091         {
15092             break;
15093         }
15094
15095         last = list;
15096         list = next;
15097     }
15098     printf(""); // null string means flush
15099 }
15100
15101 /*****************************************************************************
15102  * Callback to assert that the nodes of a qmark-colon subtree are marked
15103  */
15104
15105 /* static */
15106 Compiler::fgWalkResult Compiler::gtAssertColonCond(GenTree** pTree, fgWalkData* data)
15107 {
15108     assert(data->pCallbackData == nullptr);
15109
15110     assert((*pTree)->gtFlags & GTF_COLON_COND);
15111
15112     return WALK_CONTINUE;
15113 }
15114 #endif // DEBUG
15115
15116 /*****************************************************************************
15117  * Callback to mark the nodes of a qmark-colon subtree that are conditionally
15118  * executed.
15119  */
15120
15121 /* static */
15122 Compiler::fgWalkResult Compiler::gtMarkColonCond(GenTree** pTree, fgWalkData* data)
15123 {
15124     assert(data->pCallbackData == nullptr);
15125
15126     (*pTree)->gtFlags |= GTF_COLON_COND;
15127
15128     return WALK_CONTINUE;
15129 }
15130
15131 /*****************************************************************************
15132  * Callback to clear the conditionally executed flags of nodes that no longer
15133    will be conditionally executed. Note that when we find another colon we must
15134    stop, as the nodes below this one WILL be conditionally executed. This callback
15135    is called when folding a qmark condition (ie the condition is constant).
15136  */
15137
15138 /* static */
15139 Compiler::fgWalkResult Compiler::gtClearColonCond(GenTree** pTree, fgWalkData* data)
15140 {
15141     GenTree* tree = *pTree;
15142
15143     assert(data->pCallbackData == nullptr);
15144
15145     if (tree->OperGet() == GT_COLON)
15146     {
15147         // Nodes below this will be conditionally executed.
15148         return WALK_SKIP_SUBTREES;
15149     }
15150
15151     tree->gtFlags &= ~GTF_COLON_COND;
15152     return WALK_CONTINUE;
15153 }
15154
15155 struct FindLinkData
15156 {
15157     GenTree*  nodeToFind;
15158     GenTree** result;
15159 };
15160
15161 /*****************************************************************************
15162  *
15163  *  Callback used by the tree walker to implement fgFindLink()
15164  */
15165 static Compiler::fgWalkResult gtFindLinkCB(GenTree** pTree, Compiler::fgWalkData* cbData)
15166 {
15167     FindLinkData* data = (FindLinkData*)cbData->pCallbackData;
15168     if (*pTree == data->nodeToFind)
15169     {
15170         data->result = pTree;
15171         return Compiler::WALK_ABORT;
15172     }
15173
15174     return Compiler::WALK_CONTINUE;
15175 }
15176
15177 GenTree** Compiler::gtFindLink(GenTree* stmt, GenTree* node)
15178 {
15179     assert(stmt->gtOper == GT_STMT);
15180
15181     FindLinkData data = {node, nullptr};
15182
15183     fgWalkResult result = fgWalkTreePre(&stmt->gtStmt.gtStmtExpr, gtFindLinkCB, &data);
15184
15185     if (result == WALK_ABORT)
15186     {
15187         assert(data.nodeToFind == *data.result);
15188         return data.result;
15189     }
15190     else
15191     {
15192         return nullptr;
15193     }
15194 }
15195
15196 /*****************************************************************************
15197  *
15198  *  Callback that checks if a tree node has oper type GT_CATCH_ARG
15199  */
15200
15201 static Compiler::fgWalkResult gtFindCatchArg(GenTree** pTree, Compiler::fgWalkData* /* data */)
15202 {
15203     return ((*pTree)->OperGet() == GT_CATCH_ARG) ? Compiler::WALK_ABORT : Compiler::WALK_CONTINUE;
15204 }
15205
15206 /*****************************************************************************/
15207 bool Compiler::gtHasCatchArg(GenTree* tree)
15208 {
15209     if (((tree->gtFlags & GTF_ORDER_SIDEEFF) != 0) && (fgWalkTreePre(&tree, gtFindCatchArg) == WALK_ABORT))
15210     {
15211         return true;
15212     }
15213     return false;
15214 }
15215
15216 //------------------------------------------------------------------------
15217 // gtHasCallOnStack:
15218 //
15219 // Arguments:
15220 //    parentStack: a context (stack of parent nodes)
15221 //
15222 // Return Value:
15223 //     returns true if any of the parent nodes are a GT_CALL
15224 //
15225 // Assumptions:
15226 //    We have a stack of parent nodes. This generally requires that
15227 //    we are performing a recursive tree walk using struct fgWalkData
15228 //
15229 //------------------------------------------------------------------------
15230 /* static */ bool Compiler::gtHasCallOnStack(GenTreeStack* parentStack)
15231 {
15232     for (int i = 0; i < parentStack->Height(); i++)
15233     {
15234         GenTree* node = parentStack->Index(i);
15235         if (node->OperGet() == GT_CALL)
15236         {
15237             return true;
15238         }
15239     }
15240     return false;
15241 }
15242
15243 //------------------------------------------------------------------------
15244 // gtGetTypeProducerKind: determine if a tree produces a runtime type, and
15245 //    if so, how.
15246 //
15247 // Arguments:
15248 //    tree - tree to examine
15249 //
15250 // Return Value:
15251 //    TypeProducerKind for the tree.
15252 //
15253 // Notes:
15254 //    Checks to see if this tree returns a RuntimeType value, and if so,
15255 //    how that value is determined.
15256 //
15257 //    Currently handles these cases
15258 //    1) The result of Object::GetType
15259 //    2) The result of typeof(...)
15260 //    3) A null reference
15261 //    4) Tree is otherwise known to have type RuntimeType
15262 //
15263 //    The null reference case is surprisingly common because operator
15264 //    overloading turns the otherwise innocuous
15265 //
15266 //        Type t = ....;
15267 //        if (t == null)
15268 //
15269 //    into a method call.
15270
15271 Compiler::TypeProducerKind Compiler::gtGetTypeProducerKind(GenTree* tree)
15272 {
15273     if (tree->gtOper == GT_CALL)
15274     {
15275         if (tree->gtCall.gtCallType == CT_HELPER)
15276         {
15277             if (gtIsTypeHandleToRuntimeTypeHelper(tree->AsCall()))
15278             {
15279                 return TPK_Handle;
15280             }
15281         }
15282         else if (tree->gtCall.gtCallMoreFlags & GTF_CALL_M_SPECIAL_INTRINSIC)
15283         {
15284             if (info.compCompHnd->getIntrinsicID(tree->gtCall.gtCallMethHnd) == CORINFO_INTRINSIC_Object_GetType)
15285             {
15286                 return TPK_GetType;
15287             }
15288         }
15289     }
15290     else if ((tree->gtOper == GT_INTRINSIC) && (tree->gtIntrinsic.gtIntrinsicId == CORINFO_INTRINSIC_Object_GetType))
15291     {
15292         return TPK_GetType;
15293     }
15294     else if ((tree->gtOper == GT_CNS_INT) && (tree->gtIntCon.gtIconVal == 0))
15295     {
15296         return TPK_Null;
15297     }
15298     else
15299     {
15300         bool                 isExact   = false;
15301         bool                 isNonNull = false;
15302         CORINFO_CLASS_HANDLE clsHnd    = gtGetClassHandle(tree, &isExact, &isNonNull);
15303
15304         if (clsHnd != NO_CLASS_HANDLE && clsHnd == info.compCompHnd->getBuiltinClass(CLASSID_RUNTIME_TYPE))
15305         {
15306             return TPK_Other;
15307         }
15308     }
15309     return TPK_Unknown;
15310 }
15311
15312 //------------------------------------------------------------------------
15313 // gtIsTypeHandleToRuntimeTypeHelperCall -- see if tree is constructing
15314 //    a RuntimeType from a handle
15315 //
15316 // Arguments:
15317 //    tree - tree to examine
15318 //
15319 // Return Value:
15320 //    True if so
15321
15322 bool Compiler::gtIsTypeHandleToRuntimeTypeHelper(GenTreeCall* call)
15323 {
15324     return call->gtCallMethHnd == eeFindHelper(CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE) ||
15325            call->gtCallMethHnd == eeFindHelper(CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE_MAYBENULL);
15326 }
15327
15328 //------------------------------------------------------------------------
15329 // gtIsTypeHandleToRuntimeTypeHandleHelperCall -- see if tree is constructing
15330 //    a RuntimeTypeHandle from a handle
15331 //
15332 // Arguments:
15333 //    tree - tree to examine
15334 //    pHelper - optional pointer to a variable that receives the type of the helper
15335 //
15336 // Return Value:
15337 //    True if so
15338
15339 bool Compiler::gtIsTypeHandleToRuntimeTypeHandleHelper(GenTreeCall* call, CorInfoHelpFunc* pHelper)
15340 {
15341     CorInfoHelpFunc helper = CORINFO_HELP_UNDEF;
15342
15343     if (call->gtCallMethHnd == eeFindHelper(CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPEHANDLE))
15344     {
15345         helper = CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPEHANDLE;
15346     }
15347     else if (call->gtCallMethHnd == eeFindHelper(CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPEHANDLE_MAYBENULL))
15348     {
15349         helper = CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPEHANDLE_MAYBENULL;
15350     }
15351
15352     if (pHelper != nullptr)
15353     {
15354         *pHelper = helper;
15355     }
15356
15357     return helper != CORINFO_HELP_UNDEF;
15358 }
15359
15360 bool Compiler::gtIsActiveCSE_Candidate(GenTree* tree)
15361 {
15362     return (optValnumCSE_phase && IS_CSE_INDEX(tree->gtCSEnum));
15363 }
15364
15365 /*****************************************************************************/
15366
15367 struct ComplexityStruct
15368 {
15369     unsigned m_numNodes;
15370     unsigned m_nodeLimit;
15371     ComplexityStruct(unsigned nodeLimit) : m_numNodes(0), m_nodeLimit(nodeLimit)
15372     {
15373     }
15374 };
15375
15376 static Compiler::fgWalkResult ComplexityExceedsWalker(GenTree** pTree, Compiler::fgWalkData* data)
15377 {
15378     ComplexityStruct* pComplexity = (ComplexityStruct*)data->pCallbackData;
15379     if (++pComplexity->m_numNodes > pComplexity->m_nodeLimit)
15380     {
15381         return Compiler::WALK_ABORT;
15382     }
15383     else
15384     {
15385         return Compiler::WALK_CONTINUE;
15386     }
15387 }
15388
15389 bool Compiler::gtComplexityExceeds(GenTree** tree, unsigned limit)
15390 {
15391     ComplexityStruct complexity(limit);
15392     if (fgWalkTreePre(tree, &ComplexityExceedsWalker, &complexity) == WALK_ABORT)
15393     {
15394         return true;
15395     }
15396     else
15397     {
15398         return false;
15399     }
15400 }
15401
15402 bool GenTree::IsPhiNode()
15403 {
15404     return (OperGet() == GT_PHI_ARG) || (OperGet() == GT_PHI) || IsPhiDefn();
15405 }
15406
15407 bool GenTree::IsPhiDefn()
15408 {
15409     bool res = ((OperGet() == GT_ASG) && (gtOp.gtOp2 != nullptr) && (gtOp.gtOp2->OperGet() == GT_PHI)) ||
15410                ((OperGet() == GT_STORE_LCL_VAR) && (gtOp.gtOp1 != nullptr) && (gtOp.gtOp1->OperGet() == GT_PHI));
15411     assert(!res || OperGet() == GT_STORE_LCL_VAR || gtOp.gtOp1->OperGet() == GT_LCL_VAR);
15412     return res;
15413 }
15414
15415 bool GenTree::IsPhiDefnStmt()
15416 {
15417     if (OperGet() != GT_STMT)
15418     {
15419         return false;
15420     }
15421     GenTree* asg = gtStmt.gtStmtExpr;
15422     return asg->IsPhiDefn();
15423 }
15424
15425 // IsPartialLclFld: Check for a GT_LCL_FLD whose type is a different size than the lclVar.
15426 //
15427 // Arguments:
15428 //    comp      - the Compiler object.
15429 //
15430 // Return Value:
15431 //    Returns "true" iff 'this' is a GT_LCL_FLD or GT_STORE_LCL_FLD on which the type
15432 //    is not the same size as the type of the GT_LCL_VAR
15433
15434 bool GenTree::IsPartialLclFld(Compiler* comp)
15435 {
15436     return ((gtOper == GT_LCL_FLD) &&
15437             (comp->lvaTable[this->gtLclVarCommon.gtLclNum].lvExactSize != genTypeSize(gtType)));
15438 }
15439
15440 bool GenTree::DefinesLocal(Compiler* comp, GenTreeLclVarCommon** pLclVarTree, bool* pIsEntire)
15441 {
15442     GenTreeBlk* blkNode = nullptr;
15443     if (OperIs(GT_ASG))
15444     {
15445         if (gtOp.gtOp1->IsLocal())
15446         {
15447             GenTreeLclVarCommon* lclVarTree = gtOp.gtOp1->AsLclVarCommon();
15448             *pLclVarTree                    = lclVarTree;
15449             if (pIsEntire != nullptr)
15450             {
15451                 if (lclVarTree->IsPartialLclFld(comp))
15452                 {
15453                     *pIsEntire = false;
15454                 }
15455                 else
15456                 {
15457                     *pIsEntire = true;
15458                 }
15459             }
15460             return true;
15461         }
15462         else if (gtOp.gtOp1->OperGet() == GT_IND)
15463         {
15464             GenTree* indArg = gtOp.gtOp1->gtOp.gtOp1;
15465             return indArg->DefinesLocalAddr(comp, genTypeSize(gtOp.gtOp1->TypeGet()), pLclVarTree, pIsEntire);
15466         }
15467         else if (gtOp.gtOp1->OperIsBlk())
15468         {
15469             blkNode = gtOp.gtOp1->AsBlk();
15470         }
15471     }
15472     else if (OperIsBlk())
15473     {
15474         blkNode = this->AsBlk();
15475     }
15476     if (blkNode != nullptr)
15477     {
15478         GenTree* destAddr = blkNode->Addr();
15479         unsigned width    = blkNode->gtBlkSize;
15480         // Do we care about whether this assigns the entire variable?
15481         if (pIsEntire != nullptr && width == 0)
15482         {
15483             assert(blkNode->gtOper == GT_DYN_BLK);
15484             GenTree* blockWidth = blkNode->AsDynBlk()->gtDynamicSize;
15485             if (blockWidth->IsCnsIntOrI())
15486             {
15487                 if (blockWidth->IsIconHandle())
15488                 {
15489                     // If it's a handle, it must be a class handle.  We only create such block operations
15490                     // for initialization of struct types, so the type of the argument(s) will match this
15491                     // type, by construction, and be "entire".
15492                     assert(blockWidth->IsIconHandle(GTF_ICON_CLASS_HDL));
15493                     width = comp->info.compCompHnd->getClassSize(
15494                         CORINFO_CLASS_HANDLE(blockWidth->gtIntConCommon.IconValue()));
15495                 }
15496                 else
15497                 {
15498                     ssize_t swidth = blockWidth->AsIntConCommon()->IconValue();
15499                     assert(swidth >= 0);
15500                     // cpblk of size zero exists in the wild (in yacc-generated code in SQL) and is valid IL.
15501                     if (swidth == 0)
15502                     {
15503                         return false;
15504                     }
15505                     width = unsigned(swidth);
15506                 }
15507             }
15508         }
15509         return destAddr->DefinesLocalAddr(comp, width, pLclVarTree, pIsEntire);
15510     }
15511     // Otherwise...
15512     return false;
15513 }
15514
15515 // Returns true if this GenTree defines a result which is based on the address of a local.
15516 bool GenTree::DefinesLocalAddr(Compiler* comp, unsigned width, GenTreeLclVarCommon** pLclVarTree, bool* pIsEntire)
15517 {
15518     if (OperGet() == GT_ADDR || OperGet() == GT_LCL_VAR_ADDR)
15519     {
15520         GenTree* addrArg = this;
15521         if (OperGet() == GT_ADDR)
15522         {
15523             addrArg = gtOp.gtOp1;
15524         }
15525
15526         if (addrArg->IsLocal() || addrArg->OperIsLocalAddr())
15527         {
15528             GenTreeLclVarCommon* addrArgLcl = addrArg->AsLclVarCommon();
15529             *pLclVarTree                    = addrArgLcl;
15530             if (pIsEntire != nullptr)
15531             {
15532                 unsigned lclOffset = 0;
15533                 if (addrArg->OperIsLocalField())
15534                 {
15535                     lclOffset = addrArg->gtLclFld.gtLclOffs;
15536                 }
15537
15538                 if (lclOffset != 0)
15539                 {
15540                     // We aren't updating the bytes at [0..lclOffset-1] so *pIsEntire should be set to false
15541                     *pIsEntire = false;
15542                 }
15543                 else
15544                 {
15545                     unsigned lclNum   = addrArgLcl->GetLclNum();
15546                     unsigned varWidth = comp->lvaLclExactSize(lclNum);
15547                     if (comp->lvaTable[lclNum].lvNormalizeOnStore())
15548                     {
15549                         // It's normalize on store, so use the full storage width -- writing to low bytes won't
15550                         // necessarily yield a normalized value.
15551                         varWidth = genTypeStSz(var_types(comp->lvaTable[lclNum].lvType)) * sizeof(int);
15552                     }
15553                     *pIsEntire = (varWidth == width);
15554                 }
15555             }
15556             return true;
15557         }
15558         else if (addrArg->OperGet() == GT_IND)
15559         {
15560             // A GT_ADDR of a GT_IND can both be optimized away, recurse using the child of the GT_IND
15561             return addrArg->gtOp.gtOp1->DefinesLocalAddr(comp, width, pLclVarTree, pIsEntire);
15562         }
15563     }
15564     else if (OperGet() == GT_ADD)
15565     {
15566         if (gtOp.gtOp1->IsCnsIntOrI())
15567         {
15568             // If we just adding a zero then we allow an IsEntire match against width
15569             //  otherwise we change width to zero to disallow an IsEntire Match
15570             return gtOp.gtOp2->DefinesLocalAddr(comp, gtOp.gtOp1->IsIntegralConst(0) ? width : 0, pLclVarTree,
15571                                                 pIsEntire);
15572         }
15573         else if (gtOp.gtOp2->IsCnsIntOrI())
15574         {
15575             // If we just adding a zero then we allow an IsEntire match against width
15576             //  otherwise we change width to zero to disallow an IsEntire Match
15577             return gtOp.gtOp1->DefinesLocalAddr(comp, gtOp.gtOp2->IsIntegralConst(0) ? width : 0, pLclVarTree,
15578                                                 pIsEntire);
15579         }
15580     }
15581     // Post rationalization we could have GT_IND(GT_LEA(..)) trees.
15582     else if (OperGet() == GT_LEA)
15583     {
15584         // This method gets invoked during liveness computation and therefore it is critical
15585         // that we don't miss 'use' of any local.  The below logic is making the assumption
15586         // that in case of LEA(base, index, offset) - only base can be a GT_LCL_VAR_ADDR
15587         // and index is not.
15588         CLANG_FORMAT_COMMENT_ANCHOR;
15589
15590 #ifdef DEBUG
15591         GenTree* index = gtOp.gtOp2;
15592         if (index != nullptr)
15593         {
15594             assert(!index->DefinesLocalAddr(comp, width, pLclVarTree, pIsEntire));
15595         }
15596 #endif // DEBUG
15597
15598         // base
15599         GenTree* base = gtOp.gtOp1;
15600         if (base != nullptr)
15601         {
15602             // Lea could have an Indir as its base.
15603             if (base->OperGet() == GT_IND)
15604             {
15605                 base = base->gtOp.gtOp1->gtEffectiveVal(/*commas only*/ true);
15606             }
15607             return base->DefinesLocalAddr(comp, width, pLclVarTree, pIsEntire);
15608         }
15609     }
15610     // Otherwise...
15611     return false;
15612 }
15613
15614 //------------------------------------------------------------------------
15615 // IsLocalExpr: Determine if this is a LclVarCommon node and return some
15616 //              additional info about it in the two out parameters.
15617 //
15618 // Arguments:
15619 //    comp        - The Compiler instance
15620 //    pLclVarTree - An "out" argument that returns the local tree as a
15621 //                  LclVarCommon, if it is indeed local.
15622 //    pFldSeq     - An "out" argument that returns the value numbering field
15623 //                  sequence for the node, if any.
15624 //
15625 // Return Value:
15626 //    Returns true, and sets the out arguments accordingly, if this is
15627 //    a LclVarCommon node.
15628
15629 bool GenTree::IsLocalExpr(Compiler* comp, GenTreeLclVarCommon** pLclVarTree, FieldSeqNode** pFldSeq)
15630 {
15631     if (IsLocal()) // Note that this covers "GT_LCL_FLD."
15632     {
15633         *pLclVarTree = AsLclVarCommon();
15634         if (OperGet() == GT_LCL_FLD)
15635         {
15636             // Otherwise, prepend this field to whatever we've already accumulated outside in.
15637             *pFldSeq = comp->GetFieldSeqStore()->Append(AsLclFld()->gtFieldSeq, *pFldSeq);
15638         }
15639         return true;
15640     }
15641     else
15642     {
15643         return false;
15644     }
15645 }
15646
15647 // If this tree evaluates some sum of a local address and some constants,
15648 // return the node for the local being addressed
15649
15650 GenTreeLclVarCommon* GenTree::IsLocalAddrExpr()
15651 {
15652     if (OperGet() == GT_ADDR)
15653     {
15654         return gtOp.gtOp1->IsLocal() ? gtOp.gtOp1->AsLclVarCommon() : nullptr;
15655     }
15656     else if (OperIsLocalAddr())
15657     {
15658         return this->AsLclVarCommon();
15659     }
15660     else if (OperGet() == GT_ADD)
15661     {
15662         if (gtOp.gtOp1->OperGet() == GT_CNS_INT)
15663         {
15664             return gtOp.gtOp2->IsLocalAddrExpr();
15665         }
15666         else if (gtOp.gtOp2->OperGet() == GT_CNS_INT)
15667         {
15668             return gtOp.gtOp1->IsLocalAddrExpr();
15669         }
15670     }
15671     // Otherwise...
15672     return nullptr;
15673 }
15674
15675 bool GenTree::IsLocalAddrExpr(Compiler* comp, GenTreeLclVarCommon** pLclVarTree, FieldSeqNode** pFldSeq)
15676 {
15677     if (OperGet() == GT_ADDR)
15678     {
15679         assert(!comp->compRationalIRForm);
15680         GenTree* addrArg = gtOp.gtOp1;
15681         if (addrArg->IsLocal()) // Note that this covers "GT_LCL_FLD."
15682         {
15683             *pLclVarTree = addrArg->AsLclVarCommon();
15684             if (addrArg->OperGet() == GT_LCL_FLD)
15685             {
15686                 // Otherwise, prepend this field to whatever we've already accumulated outside in.
15687                 *pFldSeq = comp->GetFieldSeqStore()->Append(addrArg->AsLclFld()->gtFieldSeq, *pFldSeq);
15688             }
15689             return true;
15690         }
15691         else
15692         {
15693             return false;
15694         }
15695     }
15696     else if (OperIsLocalAddr())
15697     {
15698         *pLclVarTree = this->AsLclVarCommon();
15699         if (this->OperGet() == GT_LCL_FLD_ADDR)
15700         {
15701             *pFldSeq = comp->GetFieldSeqStore()->Append(this->AsLclFld()->gtFieldSeq, *pFldSeq);
15702         }
15703         return true;
15704     }
15705     else if (OperGet() == GT_ADD)
15706     {
15707         if (gtOp.gtOp1->OperGet() == GT_CNS_INT)
15708         {
15709             if (gtOp.gtOp1->AsIntCon()->gtFieldSeq == nullptr)
15710             {
15711                 return false;
15712             }
15713             // Otherwise, prepend this field to whatever we've already accumulated outside in.
15714             *pFldSeq = comp->GetFieldSeqStore()->Append(gtOp.gtOp1->AsIntCon()->gtFieldSeq, *pFldSeq);
15715             return gtOp.gtOp2->IsLocalAddrExpr(comp, pLclVarTree, pFldSeq);
15716         }
15717         else if (gtOp.gtOp2->OperGet() == GT_CNS_INT)
15718         {
15719             if (gtOp.gtOp2->AsIntCon()->gtFieldSeq == nullptr)
15720             {
15721                 return false;
15722             }
15723             // Otherwise, prepend this field to whatever we've already accumulated outside in.
15724             *pFldSeq = comp->GetFieldSeqStore()->Append(gtOp.gtOp2->AsIntCon()->gtFieldSeq, *pFldSeq);
15725             return gtOp.gtOp1->IsLocalAddrExpr(comp, pLclVarTree, pFldSeq);
15726         }
15727     }
15728     // Otherwise...
15729     return false;
15730 }
15731
15732 //------------------------------------------------------------------------
15733 // IsLclVarUpdateTree: Determine whether this is an assignment tree of the
15734 //                     form Vn = Vn 'oper' 'otherTree' where Vn is a lclVar
15735 //
15736 // Arguments:
15737 //    pOtherTree - An "out" argument in which 'otherTree' will be returned.
15738 //    pOper      - An "out" argument in which 'oper' will be returned.
15739 //
15740 // Return Value:
15741 //    If the tree is of the above form, the lclNum of the variable being
15742 //    updated is returned, and 'pOtherTree' and 'pOper' are set.
15743 //    Otherwise, returns BAD_VAR_NUM.
15744 //
15745 // Notes:
15746 //    'otherTree' can have any shape.
15747 //     We avoid worrying about whether the op is commutative by only considering the
15748 //     first operand of the rhs. It is expected that most trees of this form will
15749 //     already have the lclVar on the lhs.
15750 //     TODO-CQ: Evaluate whether there are missed opportunities due to this, or
15751 //     whether gtSetEvalOrder will already have put the lclVar on the lhs in
15752 //     the cases of interest.
15753
15754 unsigned GenTree::IsLclVarUpdateTree(GenTree** pOtherTree, genTreeOps* pOper)
15755 {
15756     unsigned lclNum = BAD_VAR_NUM;
15757     if (OperIs(GT_ASG))
15758     {
15759         GenTree* lhs = gtOp.gtOp1;
15760         if (lhs->OperGet() == GT_LCL_VAR)
15761         {
15762             unsigned lhsLclNum = lhs->AsLclVarCommon()->gtLclNum;
15763             GenTree* rhs       = gtOp.gtOp2;
15764             if (rhs->OperIsBinary() && (rhs->gtOp.gtOp1->gtOper == GT_LCL_VAR) &&
15765                 (rhs->gtOp.gtOp1->AsLclVarCommon()->gtLclNum == lhsLclNum))
15766             {
15767                 lclNum      = lhsLclNum;
15768                 *pOtherTree = rhs->gtOp.gtOp2;
15769                 *pOper      = rhs->gtOper;
15770             }
15771         }
15772     }
15773     return lclNum;
15774 }
15775
15776 //------------------------------------------------------------------------
15777 // canBeContained: check whether this tree node may be a subcomponent of its parent for purposes
15778 //                 of code generation.
15779 //
15780 // Return value: returns true if it is possible to contain this node and false otherwise.
15781 bool GenTree::canBeContained() const
15782 {
15783     assert(IsLIR());
15784
15785     if (gtHasReg())
15786     {
15787         return false;
15788     }
15789
15790     // It is not possible for nodes that do not produce values or that are not containable values
15791     // to be contained.
15792     if (((OperKind() & (GTK_NOVALUE | GTK_NOCONTAIN)) != 0) || (OperIsHWIntrinsic() && !isContainableHWIntrinsic()))
15793     {
15794         return false;
15795     }
15796
15797     return true;
15798 }
15799
15800 //------------------------------------------------------------------------
15801 // isContained: check whether this tree node is a subcomponent of its parent for codegen purposes
15802 //
15803 // Return Value:
15804 //    Returns true if there is no code generated explicitly for this node.
15805 //    Essentially, it will be rolled into the code generation for the parent.
15806 //
15807 // Assumptions:
15808 //    This method relies upon the value of the GTF_CONTAINED flag.
15809 //    Therefore this method is only valid after Lowering.
15810 //    Also note that register allocation or other subsequent phases may cause
15811 //    nodes to become contained (or not) and therefore this property may change.
15812 //
15813 bool GenTree::isContained() const
15814 {
15815     assert(IsLIR());
15816     const bool isMarkedContained = ((gtFlags & GTF_CONTAINED) != 0);
15817
15818 #ifdef DEBUG
15819     if (!canBeContained())
15820     {
15821         assert(!isMarkedContained);
15822     }
15823
15824     // these actually produce a register (the flags reg, we just don't model it)
15825     // and are a separate instruction from the branch that consumes the result.
15826     // They can only produce a result if the child is a SIMD equality comparison.
15827     else if (OperKind() & GTK_RELOP)
15828     {
15829         // We have to cast away const-ness since AsOp() method is non-const.
15830         GenTree* childNode = const_cast<GenTree*>(this)->AsOp()->gtOp1;
15831         assert((isMarkedContained == false) || childNode->IsSIMDEqualityOrInequality());
15832     }
15833
15834     // these either produce a result in register or set flags reg.
15835     else if (IsSIMDEqualityOrInequality())
15836     {
15837         assert(!isMarkedContained);
15838     }
15839
15840     // if it's contained it can't be unused.
15841     if (isMarkedContained)
15842     {
15843         assert(!IsUnusedValue());
15844     }
15845 #endif // DEBUG
15846     return isMarkedContained;
15847 }
15848
15849 // return true if node is contained and an indir
15850 bool GenTree::isContainedIndir() const
15851 {
15852     return isIndir() && isContained();
15853 }
15854
15855 bool GenTree::isIndirAddrMode()
15856 {
15857     return isIndir() && AsIndir()->Addr()->OperIsAddrMode() && AsIndir()->Addr()->isContained();
15858 }
15859
15860 bool GenTree::isIndir() const
15861 {
15862     return OperGet() == GT_IND || OperGet() == GT_STOREIND;
15863 }
15864
15865 bool GenTreeIndir::HasBase()
15866 {
15867     return Base() != nullptr;
15868 }
15869
15870 bool GenTreeIndir::HasIndex()
15871 {
15872     return Index() != nullptr;
15873 }
15874
15875 GenTree* GenTreeIndir::Base()
15876 {
15877     GenTree* addr = Addr();
15878
15879     if (isIndirAddrMode())
15880     {
15881         GenTree* result = addr->AsAddrMode()->Base();
15882         if (result != nullptr)
15883         {
15884             result = result->gtEffectiveVal();
15885         }
15886         return result;
15887     }
15888     else
15889     {
15890         return addr; // TODO: why do we return 'addr' here, but we return 'nullptr' in the equivalent Index() case?
15891     }
15892 }
15893
15894 GenTree* GenTreeIndir::Index()
15895 {
15896     if (isIndirAddrMode())
15897     {
15898         GenTree* result = Addr()->AsAddrMode()->Index();
15899         if (result != nullptr)
15900         {
15901             result = result->gtEffectiveVal();
15902         }
15903         return result;
15904     }
15905     else
15906     {
15907         return nullptr;
15908     }
15909 }
15910
15911 unsigned GenTreeIndir::Scale()
15912 {
15913     if (HasIndex())
15914     {
15915         return Addr()->AsAddrMode()->gtScale;
15916     }
15917     else
15918     {
15919         return 1;
15920     }
15921 }
15922
15923 ssize_t GenTreeIndir::Offset()
15924 {
15925     if (isIndirAddrMode())
15926     {
15927         return Addr()->AsAddrMode()->Offset();
15928     }
15929     else if (Addr()->gtOper == GT_CLS_VAR_ADDR)
15930     {
15931         return static_cast<ssize_t>(reinterpret_cast<intptr_t>(Addr()->gtClsVar.gtClsVarHnd));
15932     }
15933     else if (Addr()->IsCnsIntOrI() && Addr()->isContained())
15934     {
15935         return Addr()->AsIntConCommon()->IconValue();
15936     }
15937     else
15938     {
15939         return 0;
15940     }
15941 }
15942
15943 //------------------------------------------------------------------------
15944 // GenTreeIntConCommon::ImmedValNeedsReloc: does this immediate value needs recording a relocation with the VM?
15945 //
15946 // Arguments:
15947 //    comp - Compiler instance
15948 //
15949 // Return Value:
15950 //    True if this immediate value requires us to record a relocation for it; false otherwise.
15951
15952 bool GenTreeIntConCommon::ImmedValNeedsReloc(Compiler* comp)
15953 {
15954     return comp->opts.compReloc && (gtOper == GT_CNS_INT) && IsIconHandle();
15955 }
15956
15957 //------------------------------------------------------------------------
15958 // ImmedValCanBeFolded: can this immediate value be folded for op?
15959 //
15960 // Arguments:
15961 //    comp - Compiler instance
15962 //    op - Tree operator
15963 //
15964 // Return Value:
15965 //    True if this immediate value can be folded for op; false otherwise.
15966
15967 bool GenTreeIntConCommon::ImmedValCanBeFolded(Compiler* comp, genTreeOps op)
15968 {
15969     // In general, immediate values that need relocations can't be folded.
15970     // There are cases where we do want to allow folding of handle comparisons
15971     // (e.g., typeof(T) == typeof(int)).
15972     return !ImmedValNeedsReloc(comp) || (op == GT_EQ) || (op == GT_NE);
15973 }
15974
15975 #ifdef _TARGET_AMD64_
15976 // Returns true if this absolute address fits within the base of an addr mode.
15977 // On Amd64 this effectively means, whether an absolute indirect address can
15978 // be encoded as 32-bit offset relative to IP or zero.
15979 bool GenTreeIntConCommon::FitsInAddrBase(Compiler* comp)
15980 {
15981 #ifdef DEBUG
15982     // Early out if PC-rel encoding of absolute addr is disabled.
15983     if (!comp->opts.compEnablePCRelAddr)
15984     {
15985         return false;
15986     }
15987 #endif
15988
15989     if (comp->opts.compReloc)
15990     {
15991         // During Ngen JIT is always asked to generate relocatable code.
15992         // Hence JIT will try to encode only icon handles as pc-relative offsets.
15993         return IsIconHandle() && (IMAGE_REL_BASED_REL32 == comp->eeGetRelocTypeHint((void*)IconValue()));
15994     }
15995     else
15996     {
15997         // During Jitting, we are allowed to generate non-relocatable code.
15998         // On Amd64 we can encode an absolute indirect addr as an offset relative to zero or RIP.
15999         // An absolute indir addr that can fit within 32-bits can ben encoded as an offset relative
16000         // to zero. All other absolute indir addr could be attempted to be encoded as RIP relative
16001         // based on reloc hint provided by VM.  RIP relative encoding is preferred over relative
16002         // to zero, because the former is one byte smaller than the latter.  For this reason
16003         // we check for reloc hint first and then whether addr fits in 32-bits next.
16004         //
16005         // VM starts off with an initial state to allow both data and code address to be encoded as
16006         // pc-relative offsets.  Hence JIT will attempt to encode all absolute addresses as pc-relative
16007         // offsets.  It is possible while jitting a method, an address could not be encoded as a
16008         // pc-relative offset.  In that case VM will note the overflow and will trigger re-jitting
16009         // of the method with reloc hints turned off for all future methods. Second time around
16010         // jitting will succeed since JIT will not attempt to encode data addresses as pc-relative
16011         // offsets.  Note that JIT will always attempt to relocate code addresses (.e.g call addr).
16012         // After an overflow, VM will assume any relocation recorded is for a code address and will
16013         // emit jump thunk if it cannot be encoded as pc-relative offset.
16014         return (IMAGE_REL_BASED_REL32 == comp->eeGetRelocTypeHint((void*)IconValue())) || FitsInI32();
16015     }
16016 }
16017
16018 // Returns true if this icon value is encoded as addr needs recording a relocation with VM
16019 bool GenTreeIntConCommon::AddrNeedsReloc(Compiler* comp)
16020 {
16021     if (comp->opts.compReloc)
16022     {
16023         // During Ngen JIT is always asked to generate relocatable code.
16024         // Hence JIT will try to encode only icon handles as pc-relative offsets.
16025         return IsIconHandle() && (IMAGE_REL_BASED_REL32 == comp->eeGetRelocTypeHint((void*)IconValue()));
16026     }
16027     else
16028     {
16029         return IMAGE_REL_BASED_REL32 == comp->eeGetRelocTypeHint((void*)IconValue());
16030     }
16031 }
16032
16033 #elif defined(_TARGET_X86_)
16034 // Returns true if this absolute address fits within the base of an addr mode.
16035 // On x86 all addresses are 4-bytes and can be directly encoded in an addr mode.
16036 bool GenTreeIntConCommon::FitsInAddrBase(Compiler* comp)
16037 {
16038 #ifdef DEBUG
16039     // Early out if PC-rel encoding of absolute addr is disabled.
16040     if (!comp->opts.compEnablePCRelAddr)
16041     {
16042         return false;
16043     }
16044 #endif
16045
16046     return IsCnsIntOrI();
16047 }
16048
16049 // Returns true if this icon value is encoded as addr needs recording a relocation with VM
16050 bool GenTreeIntConCommon::AddrNeedsReloc(Compiler* comp)
16051 {
16052     // If generating relocatable code, icons should be reported for recording relocatons.
16053     return comp->opts.compReloc && IsIconHandle();
16054 }
16055 #endif //_TARGET_X86_
16056
16057 bool GenTree::IsFieldAddr(Compiler* comp, GenTree** pObj, GenTree** pStatic, FieldSeqNode** pFldSeq)
16058 {
16059     FieldSeqNode* newFldSeq    = nullptr;
16060     GenTree*      baseAddr     = nullptr;
16061     bool          mustBeStatic = false;
16062
16063     FieldSeqNode* statStructFldSeq = nullptr;
16064     if (TypeGet() == TYP_REF)
16065     {
16066         // Recognize struct static field patterns...
16067         if (OperGet() == GT_IND)
16068         {
16069             GenTree*       addr = gtOp.gtOp1;
16070             GenTreeIntCon* icon = nullptr;
16071             if (addr->OperGet() == GT_CNS_INT)
16072             {
16073                 icon = addr->AsIntCon();
16074             }
16075             else if (addr->OperGet() == GT_ADD)
16076             {
16077                 // op1 should never be a field sequence (or any other kind of handle)
16078                 assert((addr->gtOp.gtOp1->gtOper != GT_CNS_INT) || !addr->gtOp.gtOp1->IsIconHandle());
16079                 if (addr->gtOp.gtOp2->OperGet() == GT_CNS_INT)
16080                 {
16081                     icon = addr->gtOp.gtOp2->AsIntCon();
16082                 }
16083             }
16084             if (icon != nullptr && !icon->IsIconHandle(GTF_ICON_STR_HDL) // String handles are a source of TYP_REFs.
16085                 && icon->gtFieldSeq != nullptr &&
16086                 icon->gtFieldSeq->m_next == nullptr // A static field should be a singleton
16087                 // TODO-Review: A pseudoField here indicates an issue - this requires investigation
16088                 // See test case src\ddsuites\src\clr\x86\CoreMangLib\Dev\Globalization\CalendarRegressions.exe
16089                 && !(FieldSeqStore::IsPseudoField(icon->gtFieldSeq->m_fieldHnd)) &&
16090                 icon->gtFieldSeq != FieldSeqStore::NotAField()) // Ignore non-fields.
16091             {
16092                 statStructFldSeq = icon->gtFieldSeq;
16093             }
16094             else
16095             {
16096                 addr = addr->gtEffectiveVal();
16097
16098                 // Perhaps it's a direct indirection of a helper call or a cse with a zero offset annotation.
16099                 if ((addr->OperGet() == GT_CALL) || (addr->OperGet() == GT_LCL_VAR))
16100                 {
16101                     FieldSeqNode* zeroFieldSeq = nullptr;
16102                     if (comp->GetZeroOffsetFieldMap()->Lookup(addr, &zeroFieldSeq))
16103                     {
16104                         if (zeroFieldSeq->m_next == nullptr)
16105                         {
16106                             statStructFldSeq = zeroFieldSeq;
16107                         }
16108                     }
16109                 }
16110             }
16111         }
16112         else if (OperGet() == GT_CLS_VAR)
16113         {
16114             GenTreeClsVar* clsVar = AsClsVar();
16115             if (clsVar->gtFieldSeq != nullptr && clsVar->gtFieldSeq->m_next == nullptr)
16116             {
16117                 statStructFldSeq = clsVar->gtFieldSeq;
16118             }
16119         }
16120         else if (OperIsLocal())
16121         {
16122             // If we have a GT_LCL_VAR, it can be result of a CSE substitution
16123             // If it is then the CSE assignment will have a ValueNum that
16124             // describes the RHS of the CSE assignment.
16125             //
16126             // The CSE could be a pointer to a boxed struct
16127             //
16128             GenTreeLclVarCommon* lclVar = AsLclVarCommon();
16129             ValueNum             vn     = gtVNPair.GetLiberal();
16130             if (vn != ValueNumStore::NoVN)
16131             {
16132                 // Is the ValueNum a MapSelect involving a SharedStatic helper?
16133                 VNFuncApp funcApp1;
16134                 if (comp->vnStore->GetVNFunc(vn, &funcApp1) && (funcApp1.m_func == VNF_MapSelect) &&
16135                     (comp->vnStore->IsSharedStatic(funcApp1.m_args[1])))
16136                 {
16137                     ValueNum mapVN = funcApp1.m_args[0];
16138                     // Is this new 'mapVN' ValueNum, a MapSelect involving a handle?
16139                     VNFuncApp funcApp2;
16140                     if (comp->vnStore->GetVNFunc(mapVN, &funcApp2) && (funcApp2.m_func == VNF_MapSelect) &&
16141                         (comp->vnStore->IsVNHandle(funcApp2.m_args[1])))
16142                     {
16143                         ValueNum fldHndVN = funcApp2.m_args[1];
16144                         // Is this new 'fldHndVN' VNhandle a FieldHandle?
16145                         unsigned flags = comp->vnStore->GetHandleFlags(fldHndVN);
16146                         if (flags == GTF_ICON_FIELD_HDL)
16147                         {
16148                             CORINFO_FIELD_HANDLE fieldHnd =
16149                                 CORINFO_FIELD_HANDLE(comp->vnStore->ConstantValue<ssize_t>(fldHndVN));
16150
16151                             // Record this field sequence in 'statStructFldSeq' as it is likely to be a Boxed Struct
16152                             // field access.
16153                             statStructFldSeq = comp->GetFieldSeqStore()->CreateSingleton(fieldHnd);
16154                         }
16155                     }
16156                 }
16157             }
16158         }
16159
16160         if (statStructFldSeq != nullptr)
16161         {
16162             assert(statStructFldSeq->m_next == nullptr);
16163             // Is this a pointer to a boxed struct?
16164             if (comp->gtIsStaticFieldPtrToBoxedStruct(TYP_REF, statStructFldSeq->m_fieldHnd))
16165             {
16166                 *pFldSeq = comp->GetFieldSeqStore()->Append(statStructFldSeq, *pFldSeq);
16167                 *pObj    = nullptr;
16168                 *pStatic = this;
16169                 return true;
16170             }
16171         }
16172
16173         // Otherwise...
16174         *pObj    = this;
16175         *pStatic = nullptr;
16176         return true;
16177     }
16178     else if (OperGet() == GT_ADD)
16179     {
16180         // If one operator is a field sequence/handle, the other operator must not also be a field sequence/handle.
16181         if ((gtOp.gtOp1->OperGet() == GT_CNS_INT) && gtOp.gtOp1->IsIconHandle())
16182         {
16183             assert((gtOp.gtOp2->gtOper != GT_CNS_INT) || !gtOp.gtOp2->IsIconHandle());
16184             newFldSeq = gtOp.gtOp1->AsIntCon()->gtFieldSeq;
16185             baseAddr  = gtOp.gtOp2;
16186         }
16187         else if (gtOp.gtOp2->OperGet() == GT_CNS_INT)
16188         {
16189             assert((gtOp.gtOp1->gtOper != GT_CNS_INT) || !gtOp.gtOp1->IsIconHandle());
16190             newFldSeq = gtOp.gtOp2->AsIntCon()->gtFieldSeq;
16191             baseAddr  = gtOp.gtOp1;
16192         }
16193     }
16194     else
16195     {
16196         // Check if "this" has a zero-offset annotation.
16197         if (!comp->GetZeroOffsetFieldMap()->Lookup(this, &newFldSeq))
16198         {
16199             // If not, this is not a field address.
16200             return false;
16201         }
16202         else
16203         {
16204             baseAddr     = this;
16205             mustBeStatic = true;
16206         }
16207     }
16208
16209     // If not we don't have a field seq, it's not a field address.
16210     if (newFldSeq == nullptr || newFldSeq == FieldSeqStore::NotAField())
16211     {
16212         return false;
16213     }
16214
16215     // Prepend this field to whatever we've already accumulated (outside-in).
16216     *pFldSeq = comp->GetFieldSeqStore()->Append(newFldSeq, *pFldSeq);
16217
16218     // Is it a static or instance field?
16219     if (!FieldSeqStore::IsPseudoField(newFldSeq->m_fieldHnd) &&
16220         comp->info.compCompHnd->isFieldStatic(newFldSeq->m_fieldHnd))
16221     {
16222         // It is a static field.  We're done.
16223         *pObj    = nullptr;
16224         *pStatic = baseAddr;
16225         return true;
16226     }
16227     else if ((baseAddr != nullptr) && !mustBeStatic)
16228     {
16229         // It's an instance field...but it must be for a struct field, since we've not yet encountered
16230         // a "TYP_REF" address.  Analyze the reset of the address.
16231         return baseAddr->gtEffectiveVal()->IsFieldAddr(comp, pObj, pStatic, pFldSeq);
16232     }
16233
16234     // Otherwise...
16235     return false;
16236 }
16237
16238 bool Compiler::gtIsStaticFieldPtrToBoxedStruct(var_types fieldNodeType, CORINFO_FIELD_HANDLE fldHnd)
16239 {
16240     if (fieldNodeType != TYP_REF)
16241     {
16242         return false;
16243     }
16244     noway_assert(fldHnd != nullptr);
16245     CorInfoType cit      = info.compCompHnd->getFieldType(fldHnd);
16246     var_types   fieldTyp = JITtype2varType(cit);
16247     return fieldTyp != TYP_REF;
16248 }
16249
16250 #ifdef FEATURE_SIMD
16251 //------------------------------------------------------------------------
16252 // gtGetSIMDZero: Get a zero value of the appropriate SIMD type.
16253 //
16254 // Arguments:
16255 //    var_types - The simdType
16256 //    baseType  - The base type we need
16257 //    simdHandle - The handle for the SIMD type
16258 //
16259 // Return Value:
16260 //    A node generating the appropriate Zero, if we are able to discern it,
16261 //    otherwise null (note that this shouldn't happen, but callers should
16262 //    be tolerant of this case).
16263
16264 GenTree* Compiler::gtGetSIMDZero(var_types simdType, var_types baseType, CORINFO_CLASS_HANDLE simdHandle)
16265 {
16266     bool found    = false;
16267     bool isHWSIMD = true;
16268     noway_assert(m_simdHandleCache != nullptr);
16269
16270     // First, determine whether this is Vector<T>.
16271     if (simdType == getSIMDVectorType())
16272     {
16273         switch (baseType)
16274         {
16275             case TYP_FLOAT:
16276                 found = (simdHandle == m_simdHandleCache->SIMDFloatHandle);
16277                 break;
16278             case TYP_DOUBLE:
16279                 found = (simdHandle == m_simdHandleCache->SIMDDoubleHandle);
16280                 break;
16281             case TYP_INT:
16282                 found = (simdHandle == m_simdHandleCache->SIMDIntHandle);
16283                 break;
16284             case TYP_USHORT:
16285                 found = (simdHandle == m_simdHandleCache->SIMDUShortHandle);
16286                 break;
16287             case TYP_UBYTE:
16288                 found = (simdHandle == m_simdHandleCache->SIMDUByteHandle);
16289                 break;
16290             case TYP_SHORT:
16291                 found = (simdHandle == m_simdHandleCache->SIMDShortHandle);
16292                 break;
16293             case TYP_BYTE:
16294                 found = (simdHandle == m_simdHandleCache->SIMDByteHandle);
16295                 break;
16296             case TYP_LONG:
16297                 found = (simdHandle == m_simdHandleCache->SIMDLongHandle);
16298                 break;
16299             case TYP_UINT:
16300                 found = (simdHandle == m_simdHandleCache->SIMDUIntHandle);
16301                 break;
16302             case TYP_ULONG:
16303                 found = (simdHandle == m_simdHandleCache->SIMDULongHandle);
16304                 break;
16305             default:
16306                 break;
16307         }
16308         if (found)
16309         {
16310             isHWSIMD = false;
16311         }
16312     }
16313
16314     if (!found)
16315     {
16316         // We must still have isHWSIMD set to true, and the only non-HW types left are the fixed types.
16317         switch (simdType)
16318         {
16319             case TYP_SIMD8:
16320                 switch (baseType)
16321                 {
16322                     case TYP_FLOAT:
16323                         if (simdHandle == m_simdHandleCache->SIMDVector2Handle)
16324                         {
16325                             isHWSIMD = false;
16326                         }
16327 #if defined(_TARGET_ARM64_) && defined(FEATURE_HW_INTRINSICS)
16328                         else
16329                         {
16330                             assert(simdHandle == m_simdHandleCache->Vector64FloatHandle);
16331                         }
16332                         break;
16333                     case TYP_INT:
16334                         assert(simdHandle == m_simdHandleCache->Vector64IntHandle);
16335                         break;
16336                     case TYP_USHORT:
16337                         assert(simdHandle == m_simdHandleCache->Vector64UShortHandle);
16338                         break;
16339                     case TYP_UBYTE:
16340                         assert(simdHandle == m_simdHandleCache->Vector64UByteHandle);
16341                         break;
16342                     case TYP_SHORT:
16343                         assert(simdHandle == m_simdHandleCache->Vector64ShortHandle);
16344                         break;
16345                     case TYP_BYTE:
16346                         assert(simdHandle == m_simdHandleCache->Vector64ByteHandle);
16347                         break;
16348                     case TYP_UINT:
16349                         assert(simdHandle == m_simdHandleCache->Vector64UIntHandle);
16350                         break;
16351 #endif // defined(_TARGET_ARM64_) && defined(FEATURE_HW_INTRINSICS)
16352                     default:
16353                         break;
16354                 }
16355                 break;
16356
16357             case TYP_SIMD12:
16358                 assert((baseType == TYP_FLOAT) && (simdHandle == m_simdHandleCache->SIMDVector3Handle));
16359                 isHWSIMD = false;
16360                 break;
16361
16362             case TYP_SIMD16:
16363                 switch (baseType)
16364                 {
16365                     case TYP_FLOAT:
16366                         if (simdHandle == m_simdHandleCache->SIMDVector4Handle)
16367                         {
16368                             isHWSIMD = false;
16369                         }
16370 #if defined(FEATURE_HW_INTRINSICS)
16371                         else
16372                         {
16373                             assert(simdHandle == m_simdHandleCache->Vector128FloatHandle);
16374                         }
16375                         break;
16376                     case TYP_DOUBLE:
16377                         assert(simdHandle == m_simdHandleCache->Vector128DoubleHandle);
16378                         break;
16379                     case TYP_INT:
16380                         assert(simdHandle == m_simdHandleCache->Vector128IntHandle);
16381                         break;
16382                     case TYP_USHORT:
16383                         assert(simdHandle == m_simdHandleCache->Vector128UShortHandle);
16384                         break;
16385                     case TYP_UBYTE:
16386                         assert(simdHandle == m_simdHandleCache->Vector128UByteHandle);
16387                         break;
16388                     case TYP_SHORT:
16389                         assert(simdHandle == m_simdHandleCache->Vector128ShortHandle);
16390                         break;
16391                     case TYP_BYTE:
16392                         assert(simdHandle == m_simdHandleCache->Vector128ByteHandle);
16393                         break;
16394                     case TYP_LONG:
16395                         assert(simdHandle == m_simdHandleCache->Vector128LongHandle);
16396                         break;
16397                     case TYP_UINT:
16398                         assert(simdHandle == m_simdHandleCache->Vector128UIntHandle);
16399                         break;
16400                     case TYP_ULONG:
16401                         assert(simdHandle == m_simdHandleCache->Vector128ULongHandle);
16402                         break;
16403 #endif // defined(FEATURE_HW_INTRINSICS)
16404
16405                     default:
16406                         break;
16407                 }
16408                 break;
16409
16410 #if defined(_TARGET_XARCH4_) && defined(FEATURE_HW_INTRINSICS)
16411             case TYP_SIMD32:
16412                 switch (baseType)
16413                 {
16414                     case TYP_FLOAT:
16415                         assert(simdHandle == m_simdHandleCache->Vector256FloatHandle);
16416                         break;
16417                     case TYP_DOUBLE:
16418                         assert(simdHandle == m_simdHandleCache->Vector256DoubleHandle);
16419                         break;
16420                     case TYP_INT:
16421                         assert(simdHandle == m_simdHandleCache->Vector256IntHandle);
16422                         break;
16423                     case TYP_USHORT:
16424                         assert(simdHandle == m_simdHandleCache->Vector256UShortHandle);
16425                         break;
16426                     case TYP_UBYTE:
16427                         assert(simdHandle == m_simdHandleCache->Vector256UByteHandle);
16428                         break;
16429                     case TYP_SHORT:
16430                         assert(simdHandle == m_simdHandleCache->Vector256ShortHandle);
16431                         break;
16432                     case TYP_BYTE:
16433                         assert(simdHandle == m_simdHandleCache->Vector256ByteHandle);
16434                         break;
16435                     case TYP_LONG:
16436                         assert(simdHandle == m_simdHandleCache->Vector256LongHandle);
16437                         break;
16438                     case TYP_UINT:
16439                         assert(simdHandle == m_simdHandleCache->Vector256UIntHandle);
16440                         break;
16441                     case TYP_ULONG:
16442                         assert(simdHandle == m_simdHandleCache->Vector256ULongHandle);
16443                         break;
16444                     default:
16445                         break;
16446                 }
16447                 break;
16448 #endif // _TARGET_XARCH_ && FEATURE_HW_INTRINSICS
16449             default:
16450                 break;
16451         }
16452     }
16453
16454     unsigned size = genTypeSize(simdType);
16455     if (isHWSIMD)
16456     {
16457 #if defined(_TARGET_XARCH_) && defined(FEATURE_HW_INTRINSICS)
16458         switch (simdType)
16459         {
16460             case TYP_SIMD16:
16461                 if (compSupports(InstructionSet_SSE))
16462                 {
16463                     // We only return the HWIntrinsicNode if SSE is supported, since it is possible for
16464                     // the user to disable the SSE HWIntrinsic support via the COMPlus configuration knobs
16465                     // even though the hardware vector types are still available.
16466                     return gtNewSimdHWIntrinsicNode(simdType, NI_Base_Vector128_Zero, baseType, size);
16467                 }
16468                 return nullptr;
16469             case TYP_SIMD32:
16470                 if (compSupports(InstructionSet_AVX))
16471                 {
16472                     // We only return the HWIntrinsicNode if AVX is supported, since it is possible for
16473                     // the user to disable the AVX HWIntrinsic support via the COMPlus configuration knobs
16474                     // even though the hardware vector types are still available.
16475                     return gtNewSimdHWIntrinsicNode(simdType, NI_Base_Vector256_Zero, baseType, size);
16476                 }
16477                 return nullptr;
16478             default:
16479                 break;
16480         }
16481 #endif // _TARGET_XARCH_ && FEATURE_HW_INTRINSICS
16482         JITDUMP("Coudn't find the matching SIMD type for %s<%s> in gtGetSIMDZero\n", varTypeName(simdType),
16483                 varTypeName(baseType));
16484     }
16485     else
16486     {
16487         return gtNewSIMDVectorZero(simdType, baseType, size);
16488     }
16489     return nullptr;
16490 }
16491 #endif // FEATURE_SIMD
16492
16493 CORINFO_CLASS_HANDLE Compiler::gtGetStructHandleIfPresent(GenTree* tree)
16494 {
16495     CORINFO_CLASS_HANDLE structHnd = NO_CLASS_HANDLE;
16496     tree                           = tree->gtEffectiveVal();
16497     if (varTypeIsStruct(tree->gtType))
16498     {
16499         switch (tree->gtOper)
16500         {
16501             default:
16502                 break;
16503             case GT_MKREFANY:
16504                 structHnd = impGetRefAnyClass();
16505                 break;
16506             case GT_OBJ:
16507                 structHnd = tree->gtObj.gtClass;
16508                 break;
16509             case GT_CALL:
16510                 structHnd = tree->gtCall.gtRetClsHnd;
16511                 break;
16512             case GT_RET_EXPR:
16513                 structHnd = tree->gtRetExpr.gtRetClsHnd;
16514                 break;
16515             case GT_ARGPLACE:
16516                 structHnd = tree->gtArgPlace.gtArgPlaceClsHnd;
16517                 break;
16518             case GT_INDEX:
16519                 structHnd = tree->gtIndex.gtStructElemClass;
16520                 break;
16521             case GT_INDEX_ADDR:
16522                 structHnd = tree->AsIndexAddr()->gtStructElemClass;
16523                 break;
16524             case GT_FIELD:
16525                 info.compCompHnd->getFieldType(tree->gtField.gtFldHnd, &structHnd);
16526                 break;
16527             case GT_ASG:
16528                 structHnd = gtGetStructHandleIfPresent(tree->gtGetOp1());
16529                 break;
16530             case GT_LCL_FLD:
16531 #ifdef FEATURE_SIMD
16532                 if (varTypeIsSIMD(tree))
16533                 {
16534                     structHnd = gtGetStructHandleForSIMD(tree->gtType, TYP_FLOAT);
16535                 }
16536 #endif
16537                 break;
16538             case GT_LCL_VAR:
16539                 structHnd = lvaTable[tree->AsLclVarCommon()->gtLclNum].lvVerTypeInfo.GetClassHandle();
16540                 break;
16541             case GT_RETURN:
16542                 structHnd = gtGetStructHandleIfPresent(tree->gtOp.gtOp1);
16543                 break;
16544             case GT_IND:
16545 #ifdef FEATURE_SIMD
16546                 if (varTypeIsSIMD(tree))
16547                 {
16548                     structHnd = gtGetStructHandleForSIMD(tree->gtType, TYP_FLOAT);
16549                 }
16550                 else
16551 #endif
16552                 {
16553                     ArrayInfo arrInfo;
16554                     if (TryGetArrayInfo(tree->AsIndir(), &arrInfo))
16555                     {
16556                         structHnd = EncodeElemType(arrInfo.m_elemType, arrInfo.m_elemStructType);
16557                     }
16558                 }
16559                 break;
16560 #ifdef FEATURE_SIMD
16561             case GT_SIMD:
16562                 structHnd = gtGetStructHandleForSIMD(tree->gtType, tree->AsSIMD()->gtSIMDBaseType);
16563                 break;
16564 #endif // FEATURE_SIMD
16565 #ifdef FEATURE_HW_INTRINSICS
16566             case GT_HWIntrinsic:
16567                 structHnd = gtGetStructHandleForHWSIMD(tree->gtType, tree->AsHWIntrinsic()->gtSIMDBaseType);
16568                 break;
16569 #endif
16570                 break;
16571         }
16572     }
16573     return structHnd;
16574 }
16575
16576 CORINFO_CLASS_HANDLE Compiler::gtGetStructHandle(GenTree* tree)
16577 {
16578     CORINFO_CLASS_HANDLE structHnd = gtGetStructHandleIfPresent(tree);
16579     assert(structHnd != NO_CLASS_HANDLE);
16580     return structHnd;
16581 }
16582
16583 //------------------------------------------------------------------------
16584 // gtGetClassHandle: find class handle for a ref type
16585 //
16586 // Arguments:
16587 //    tree -- tree to find handle for
16588 //    pIsExact   [out] -- whether handle is exact type
16589 //    pIsNonNull [out] -- whether tree value is known not to be null
16590 //
16591 // Return Value:
16592 //    nullptr if class handle is unknown,
16593 //        otherwise the class handle.
16594 //    *pIsExact set true if tree type is known to be exactly the handle type,
16595 //        otherwise actual type may be a subtype.
16596 //    *pIsNonNull set true if tree value is known not to be null,
16597 //        otherwise a null value is possible.
16598
16599 CORINFO_CLASS_HANDLE Compiler::gtGetClassHandle(GenTree* tree, bool* pIsExact, bool* pIsNonNull)
16600 {
16601     // Set default values for our out params.
16602     *pIsNonNull                   = false;
16603     *pIsExact                     = false;
16604     CORINFO_CLASS_HANDLE objClass = nullptr;
16605
16606     // Bail out if we're just importing and not generating code, since
16607     // the jit uses TYP_REF for CORINFO_TYPE_VAR locals and args, but
16608     // these may not be ref types.
16609     if (compIsForImportOnly())
16610     {
16611         return objClass;
16612     }
16613
16614     // Bail out if the tree is not a ref type.
16615     var_types treeType = tree->TypeGet();
16616     if (treeType != TYP_REF)
16617     {
16618         return objClass;
16619     }
16620
16621     // Tunnel through commas.
16622     GenTree*         obj   = tree->gtEffectiveVal(false);
16623     const genTreeOps objOp = obj->OperGet();
16624
16625     switch (objOp)
16626     {
16627         case GT_COMMA:
16628         {
16629             // gtEffectiveVal above means we shouldn't see commas here.
16630             assert(!"unexpected GT_COMMA");
16631             break;
16632         }
16633
16634         case GT_LCL_VAR:
16635         {
16636             // For locals, pick up type info from the local table.
16637             const unsigned objLcl = obj->AsLclVar()->GetLclNum();
16638
16639             objClass  = lvaTable[objLcl].lvClassHnd;
16640             *pIsExact = lvaTable[objLcl].lvClassIsExact;
16641             break;
16642         }
16643
16644         case GT_FIELD:
16645         {
16646             // For fields, get the type from the field handle.
16647             CORINFO_FIELD_HANDLE fieldHnd = obj->gtField.gtFldHnd;
16648
16649             if (fieldHnd != nullptr)
16650             {
16651                 objClass = gtGetFieldClassHandle(fieldHnd, pIsExact, pIsNonNull);
16652             }
16653
16654             break;
16655         }
16656
16657         case GT_RET_EXPR:
16658         {
16659             // If we see a RET_EXPR, recurse through to examine the
16660             // return value expression.
16661             GenTree* retExpr = tree->gtRetExpr.gtInlineCandidate;
16662             objClass         = gtGetClassHandle(retExpr, pIsExact, pIsNonNull);
16663             break;
16664         }
16665
16666         case GT_CALL:
16667         {
16668             GenTreeCall* call = tree->AsCall();
16669             if (call->IsInlineCandidate())
16670             {
16671                 // For inline candidates, we've already cached the return
16672                 // type class handle in the inline info.
16673                 InlineCandidateInfo* inlInfo = call->gtInlineCandidateInfo;
16674                 assert(inlInfo != nullptr);
16675
16676                 // Grab it as our first cut at a return type.
16677                 assert(inlInfo->methInfo.args.retType == CORINFO_TYPE_CLASS);
16678                 objClass = inlInfo->methInfo.args.retTypeClass;
16679
16680                 // If the method is shared, the above may not capture
16681                 // the most precise return type information (that is,
16682                 // it may represent a shared return type and as such,
16683                 // have instances of __Canon). See if we can use the
16684                 // context to get at something more definite.
16685                 //
16686                 // For now, we do this here on demand rather than when
16687                 // processing the call, but we could/should apply
16688                 // similar sharpening to the argument and local types
16689                 // of the inlinee.
16690                 const unsigned retClassFlags = info.compCompHnd->getClassAttribs(objClass);
16691                 if (retClassFlags & CORINFO_FLG_SHAREDINST)
16692                 {
16693                     CORINFO_CONTEXT_HANDLE context = inlInfo->exactContextHnd;
16694
16695                     if (context != nullptr)
16696                     {
16697                         CORINFO_CLASS_HANDLE exactClass = nullptr;
16698
16699                         if (((size_t)context & CORINFO_CONTEXTFLAGS_MASK) == CORINFO_CONTEXTFLAGS_CLASS)
16700                         {
16701                             exactClass = (CORINFO_CLASS_HANDLE)((size_t)context & ~CORINFO_CONTEXTFLAGS_MASK);
16702                         }
16703                         else
16704                         {
16705                             CORINFO_METHOD_HANDLE exactMethod =
16706                                 (CORINFO_METHOD_HANDLE)((size_t)context & ~CORINFO_CONTEXTFLAGS_MASK);
16707                             exactClass = info.compCompHnd->getMethodClass(exactMethod);
16708                         }
16709
16710                         // Grab the signature in this context.
16711                         CORINFO_SIG_INFO sig;
16712                         eeGetMethodSig(call->gtCallMethHnd, &sig, exactClass);
16713                         assert(sig.retType == CORINFO_TYPE_CLASS);
16714                         objClass = sig.retTypeClass;
16715                     }
16716                 }
16717             }
16718             else if (call->gtCallType == CT_USER_FUNC)
16719             {
16720                 // For user calls, we can fetch the approximate return
16721                 // type info from the method handle. Unfortunately
16722                 // we've lost the exact context, so this is the best
16723                 // we can do for now.
16724                 CORINFO_METHOD_HANDLE method     = call->gtCallMethHnd;
16725                 CORINFO_CLASS_HANDLE  exactClass = nullptr;
16726                 CORINFO_SIG_INFO      sig;
16727                 eeGetMethodSig(method, &sig, exactClass);
16728                 if (sig.retType == CORINFO_TYPE_VOID)
16729                 {
16730                     // This is a constructor call.
16731                     const unsigned methodFlags = info.compCompHnd->getMethodAttribs(method);
16732                     assert((methodFlags & CORINFO_FLG_CONSTRUCTOR) != 0);
16733                     objClass    = info.compCompHnd->getMethodClass(method);
16734                     *pIsExact   = true;
16735                     *pIsNonNull = true;
16736                 }
16737                 else
16738                 {
16739                     assert(sig.retType == CORINFO_TYPE_CLASS);
16740                     objClass = sig.retTypeClass;
16741                 }
16742             }
16743             else if (call->gtCallType == CT_HELPER)
16744             {
16745                 objClass = gtGetHelperCallClassHandle(call, pIsExact, pIsNonNull);
16746             }
16747
16748             break;
16749         }
16750
16751         case GT_INTRINSIC:
16752         {
16753             GenTreeIntrinsic* intrinsic = obj->AsIntrinsic();
16754
16755             if (intrinsic->gtIntrinsicId == CORINFO_INTRINSIC_Object_GetType)
16756             {
16757                 CORINFO_CLASS_HANDLE runtimeType = info.compCompHnd->getBuiltinClass(CLASSID_RUNTIME_TYPE);
16758                 assert(runtimeType != NO_CLASS_HANDLE);
16759
16760                 objClass    = runtimeType;
16761                 *pIsExact   = false;
16762                 *pIsNonNull = true;
16763             }
16764
16765             break;
16766         }
16767
16768         case GT_CNS_STR:
16769         {
16770             // For literal strings, we know the class and that the
16771             // value is not null.
16772             objClass    = impGetStringClass();
16773             *pIsExact   = true;
16774             *pIsNonNull = true;
16775             break;
16776         }
16777
16778         case GT_IND:
16779         {
16780             GenTreeIndir* indir = obj->AsIndir();
16781
16782             if (indir->HasBase() && !indir->HasIndex())
16783             {
16784                 // indir(addr(lcl)) --> lcl
16785                 //
16786                 // This comes up during constrained callvirt on ref types.
16787
16788                 GenTree*             base = indir->Base();
16789                 GenTreeLclVarCommon* lcl  = base->IsLocalAddrExpr();
16790
16791                 if ((lcl != nullptr) && (base->OperGet() != GT_ADD))
16792                 {
16793                     const unsigned objLcl = lcl->GetLclNum();
16794                     objClass              = lvaTable[objLcl].lvClassHnd;
16795                     *pIsExact             = lvaTable[objLcl].lvClassIsExact;
16796                 }
16797                 else if (base->OperGet() == GT_ARR_ELEM)
16798                 {
16799                     // indir(arr_elem(...)) -> array element type
16800
16801                     GenTree* array = base->AsArrElem()->gtArrObj;
16802
16803                     objClass    = gtGetArrayElementClassHandle(array);
16804                     *pIsExact   = false;
16805                     *pIsNonNull = false;
16806                 }
16807                 else if (base->OperGet() == GT_ADD)
16808                 {
16809                     // This could be a static field access.
16810                     //
16811                     // See if op1 is a static field base helper call
16812                     // and if so, op2 will have the field info.
16813                     GenTree* op1 = base->gtOp.gtOp1;
16814                     GenTree* op2 = base->gtOp.gtOp2;
16815
16816                     const bool op1IsStaticFieldBase = gtIsStaticGCBaseHelperCall(op1);
16817
16818                     if (op1IsStaticFieldBase && (op2->OperGet() == GT_CNS_INT))
16819                     {
16820                         FieldSeqNode* fieldSeq = op2->AsIntCon()->gtFieldSeq;
16821
16822                         if (fieldSeq != nullptr)
16823                         {
16824                             while (fieldSeq->m_next != nullptr)
16825                             {
16826                                 fieldSeq = fieldSeq->m_next;
16827                             }
16828
16829                             assert(!fieldSeq->IsPseudoField());
16830
16831                             // No benefit to calling gtGetFieldClassHandle here, as
16832                             // the exact field being accessed can vary.
16833                             CORINFO_FIELD_HANDLE fieldHnd     = fieldSeq->m_fieldHnd;
16834                             CORINFO_CLASS_HANDLE fieldClass   = nullptr;
16835                             CorInfoType          fieldCorType = info.compCompHnd->getFieldType(fieldHnd, &fieldClass);
16836
16837                             assert(fieldCorType == CORINFO_TYPE_CLASS);
16838                             objClass = fieldClass;
16839                         }
16840                     }
16841                 }
16842             }
16843
16844             break;
16845         }
16846
16847         case GT_BOX:
16848         {
16849             // Box should just wrap a local var reference which has
16850             // the type we're looking for. Also box only represents a
16851             // non-nullable value type so result cannot be null.
16852             GenTreeBox* box     = obj->AsBox();
16853             GenTree*    boxTemp = box->BoxOp();
16854             assert(boxTemp->IsLocal());
16855             const unsigned boxTempLcl = boxTemp->AsLclVar()->GetLclNum();
16856             objClass                  = lvaTable[boxTempLcl].lvClassHnd;
16857             *pIsExact                 = lvaTable[boxTempLcl].lvClassIsExact;
16858             *pIsNonNull               = true;
16859             break;
16860         }
16861
16862         case GT_INDEX:
16863         {
16864             GenTree* array = obj->AsIndex()->Arr();
16865
16866             objClass    = gtGetArrayElementClassHandle(array);
16867             *pIsExact   = false;
16868             *pIsNonNull = false;
16869             break;
16870         }
16871
16872         default:
16873         {
16874             break;
16875         }
16876     }
16877
16878     return objClass;
16879 }
16880
16881 //------------------------------------------------------------------------
16882 // gtGetHelperCallClassHandle: find class handle for return value of a
16883 //   helper call
16884 //
16885 // Arguments:
16886 //    call - helper call to examine
16887 //    pIsExact - [OUT] true if type is known exactly
16888 //    pIsNonNull - [OUT] true if return value is not null
16889 //
16890 // Return Value:
16891 //    nullptr if helper call result is not a ref class, or the class handle
16892 //    is unknown, otherwise the class handle.
16893
16894 CORINFO_CLASS_HANDLE Compiler::gtGetHelperCallClassHandle(GenTreeCall* call, bool* pIsExact, bool* pIsNonNull)
16895 {
16896     assert(call->gtCallType == CT_HELPER);
16897
16898     *pIsNonNull                    = false;
16899     *pIsExact                      = false;
16900     CORINFO_CLASS_HANDLE  objClass = nullptr;
16901     const CorInfoHelpFunc helper   = eeGetHelperNum(call->gtCallMethHnd);
16902
16903     switch (helper)
16904     {
16905         case CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE:
16906         case CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE_MAYBENULL:
16907         {
16908             // Note for some runtimes these helpers return exact types.
16909             //
16910             // But in those cases the types are also sealed, so there's no
16911             // need to claim exactness here.
16912             const bool           helperResultNonNull = (helper == CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE);
16913             CORINFO_CLASS_HANDLE runtimeType         = info.compCompHnd->getBuiltinClass(CLASSID_RUNTIME_TYPE);
16914
16915             assert(runtimeType != NO_CLASS_HANDLE);
16916
16917             objClass    = runtimeType;
16918             *pIsNonNull = helperResultNonNull;
16919             break;
16920         }
16921
16922         case CORINFO_HELP_CHKCASTCLASS:
16923         case CORINFO_HELP_CHKCASTANY:
16924         case CORINFO_HELP_CHKCASTARRAY:
16925         case CORINFO_HELP_CHKCASTINTERFACE:
16926         case CORINFO_HELP_CHKCASTCLASS_SPECIAL:
16927         case CORINFO_HELP_ISINSTANCEOFINTERFACE:
16928         case CORINFO_HELP_ISINSTANCEOFARRAY:
16929         case CORINFO_HELP_ISINSTANCEOFCLASS:
16930         case CORINFO_HELP_ISINSTANCEOFANY:
16931         {
16932             // Fetch the class handle from the helper call arglist
16933             GenTreeArgList*      args    = call->gtCallArgs;
16934             GenTree*             typeArg = args->Current();
16935             CORINFO_CLASS_HANDLE castHnd = gtGetHelperArgClassHandle(typeArg);
16936
16937             // We generally assume the type being cast to is the best type
16938             // for the result, unless it is an interface type.
16939             //
16940             // TODO-CQ: when we have default interface methods then
16941             // this might not be the best assumption. We could also
16942             // explore calling something like mergeClasses to identify
16943             // the more specific class. A similar issue arises when
16944             // typing the temp in impCastClassOrIsInstToTree, when we
16945             // expand the cast inline.
16946             if (castHnd != nullptr)
16947             {
16948                 DWORD attrs = info.compCompHnd->getClassAttribs(castHnd);
16949
16950                 if ((attrs & CORINFO_FLG_INTERFACE) != 0)
16951                 {
16952                     castHnd = nullptr;
16953                 }
16954             }
16955
16956             // If we don't have a good estimate for the type we can use the
16957             // type from the value being cast instead.
16958             if (castHnd == nullptr)
16959             {
16960                 GenTree* valueArg = args->Rest()->Current();
16961                 castHnd           = gtGetClassHandle(valueArg, pIsExact, pIsNonNull);
16962             }
16963
16964             // We don't know at jit time if the cast will succeed or fail, but if it
16965             // fails at runtime then an exception is thrown for cast helpers, or the
16966             // result is set null for instance helpers.
16967             //
16968             // So it safe to claim the result has the cast type.
16969             // Note we don't know for sure that it is exactly this type.
16970             if (castHnd != nullptr)
16971             {
16972                 objClass = castHnd;
16973             }
16974
16975             break;
16976         }
16977
16978         default:
16979             break;
16980     }
16981
16982     return objClass;
16983 }
16984
16985 //------------------------------------------------------------------------
16986 // gtGetArrayElementClassHandle: find class handle for elements of an array
16987 // of ref types
16988 //
16989 // Arguments:
16990 //    array -- array to find handle for
16991 //
16992 // Return Value:
16993 //    nullptr if element class handle is unknown, otherwise the class handle.
16994
16995 CORINFO_CLASS_HANDLE Compiler::gtGetArrayElementClassHandle(GenTree* array)
16996 {
16997     bool                 isArrayExact   = false;
16998     bool                 isArrayNonNull = false;
16999     CORINFO_CLASS_HANDLE arrayClassHnd  = gtGetClassHandle(array, &isArrayExact, &isArrayNonNull);
17000
17001     if (arrayClassHnd != nullptr)
17002     {
17003         // We know the class of the reference
17004         DWORD attribs = info.compCompHnd->getClassAttribs(arrayClassHnd);
17005
17006         if ((attribs & CORINFO_FLG_ARRAY) != 0)
17007         {
17008             // We know for sure it is an array
17009             CORINFO_CLASS_HANDLE elemClassHnd  = nullptr;
17010             CorInfoType          arrayElemType = info.compCompHnd->getChildType(arrayClassHnd, &elemClassHnd);
17011
17012             if (arrayElemType == CORINFO_TYPE_CLASS)
17013             {
17014                 // We know it is an array of ref types
17015                 return elemClassHnd;
17016             }
17017         }
17018     }
17019
17020     return nullptr;
17021 }
17022
17023 //------------------------------------------------------------------------
17024 // gtGetFieldClassHandle: find class handle for a field
17025 //
17026 // Arguments:
17027 //    fieldHnd - field handle for field in question
17028 //    pIsExact - [OUT] true if type is known exactly
17029 //    pIsNonNull - [OUT] true if field value is not null
17030 //
17031 // Return Value:
17032 //    nullptr if helper call result is not a ref class, or the class handle
17033 //    is unknown, otherwise the class handle.
17034 //
17035 //    May examine runtime state of static field instances.
17036
17037 CORINFO_CLASS_HANDLE Compiler::gtGetFieldClassHandle(CORINFO_FIELD_HANDLE fieldHnd, bool* pIsExact, bool* pIsNonNull)
17038 {
17039     CORINFO_CLASS_HANDLE fieldClass   = nullptr;
17040     CorInfoType          fieldCorType = info.compCompHnd->getFieldType(fieldHnd, &fieldClass);
17041
17042     if (fieldCorType == CORINFO_TYPE_CLASS)
17043     {
17044         // Optionally, look at the actual type of the field's value
17045         bool queryForCurrentClass = true;
17046         INDEBUG(queryForCurrentClass = (JitConfig.JitQueryCurrentStaticFieldClass() > 0););
17047
17048         if (queryForCurrentClass)
17049         {
17050
17051 #if DEBUG
17052             const char* fieldClassName = nullptr;
17053             const char* fieldName      = eeGetFieldName(fieldHnd, &fieldClassName);
17054             JITDUMP("Querying runtime about current class of field %s.%s (declared as %s)\n", fieldClassName, fieldName,
17055                     eeGetClassName(fieldClass));
17056 #endif // DEBUG
17057
17058             // Is this a fully initialized init-only static field?
17059             //
17060             // Note we're not asking for speculative results here, yet.
17061             CORINFO_CLASS_HANDLE currentClass = info.compCompHnd->getStaticFieldCurrentClass(fieldHnd);
17062
17063             if (currentClass != NO_CLASS_HANDLE)
17064             {
17065                 // Yes! We know the class exactly and can rely on this to always be true.
17066                 fieldClass  = currentClass;
17067                 *pIsExact   = true;
17068                 *pIsNonNull = true;
17069                 JITDUMP("Runtime reports field is init-only and initialized and has class %s\n",
17070                         eeGetClassName(fieldClass));
17071             }
17072             else
17073             {
17074                 JITDUMP("Field's current class not available\n");
17075             }
17076         }
17077     }
17078
17079     return fieldClass;
17080 }
17081
17082 //------------------------------------------------------------------------
17083 // gtIsGCStaticBaseHelperCall: true if tree is fetching the gc static base
17084 //    for a subsequent static field access
17085 //
17086 // Arguments:
17087 //    tree - tree to consider
17088 //
17089 // Return Value:
17090 //    true if the tree is a suitable helper call
17091 //
17092 // Notes:
17093 //    Excludes R2R helpers as they specify the target field in a way
17094 //    that is opaque to the jit.
17095
17096 bool Compiler::gtIsStaticGCBaseHelperCall(GenTree* tree)
17097 {
17098     if (tree->OperGet() != GT_CALL)
17099     {
17100         return false;
17101     }
17102
17103     GenTreeCall* call = tree->AsCall();
17104
17105     if (call->gtCallType != CT_HELPER)
17106     {
17107         return false;
17108     }
17109
17110     const CorInfoHelpFunc helper = eeGetHelperNum(call->gtCallMethHnd);
17111
17112     switch (helper)
17113     {
17114         // We are looking for a REF type so only need to check for the GC base helpers
17115         case CORINFO_HELP_GETGENERICS_GCSTATIC_BASE:
17116         case CORINFO_HELP_GETSHARED_GCSTATIC_BASE:
17117         case CORINFO_HELP_GETSHARED_GCSTATIC_BASE_NOCTOR:
17118         case CORINFO_HELP_GETSHARED_GCSTATIC_BASE_DYNAMICCLASS:
17119         case CORINFO_HELP_GETGENERICS_GCTHREADSTATIC_BASE:
17120         case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE:
17121         case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR:
17122         case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_DYNAMICCLASS:
17123             return true;
17124         default:
17125             break;
17126     }
17127
17128     return false;
17129 }
17130
17131 void GenTree::ParseArrayAddress(
17132     Compiler* comp, ArrayInfo* arrayInfo, GenTree** pArr, ValueNum* pInxVN, FieldSeqNode** pFldSeq)
17133 {
17134     *pArr                 = nullptr;
17135     ValueNum       inxVN  = ValueNumStore::NoVN;
17136     target_ssize_t offset = 0;
17137     FieldSeqNode*  fldSeq = nullptr;
17138
17139     ParseArrayAddressWork(comp, 1, pArr, &inxVN, &offset, &fldSeq);
17140
17141     // If we didn't find an array reference (perhaps it is the constant null?) we will give up.
17142     if (*pArr == nullptr)
17143     {
17144         return;
17145     }
17146
17147     // OK, new we have to figure out if any part of the "offset" is a constant contribution to the index.
17148     // First, sum the offsets of any fields in fldSeq.
17149     unsigned      fieldOffsets = 0;
17150     FieldSeqNode* fldSeqIter   = fldSeq;
17151     // Also, find the first non-pseudo field...
17152     assert(*pFldSeq == nullptr);
17153     while (fldSeqIter != nullptr)
17154     {
17155         if (fldSeqIter == FieldSeqStore::NotAField())
17156         {
17157             // TODO-Review: A NotAField here indicates a failure to properly maintain the field sequence
17158             // See test case self_host_tests_x86\jit\regression\CLR-x86-JIT\v1-m12-beta2\ b70992\ b70992.exe
17159             // Safest thing to do here is to drop back to MinOpts
17160             CLANG_FORMAT_COMMENT_ANCHOR;
17161
17162 #ifdef DEBUG
17163             if (comp->opts.optRepeat)
17164             {
17165                 // We don't guarantee preserving these annotations through the entire optimizer, so
17166                 // just conservatively return null if under optRepeat.
17167                 *pArr = nullptr;
17168                 return;
17169             }
17170 #endif // DEBUG
17171             noway_assert(!"fldSeqIter is NotAField() in ParseArrayAddress");
17172         }
17173
17174         if (!FieldSeqStore::IsPseudoField(fldSeqIter->m_fieldHnd))
17175         {
17176             if (*pFldSeq == nullptr)
17177             {
17178                 *pFldSeq = fldSeqIter;
17179             }
17180             CORINFO_CLASS_HANDLE fldCls = nullptr;
17181             noway_assert(fldSeqIter->m_fieldHnd != nullptr);
17182             CorInfoType cit = comp->info.compCompHnd->getFieldType(fldSeqIter->m_fieldHnd, &fldCls);
17183             fieldOffsets += comp->compGetTypeSize(cit, fldCls);
17184         }
17185         fldSeqIter = fldSeqIter->m_next;
17186     }
17187
17188     // Is there some portion of the "offset" beyond the first-elem offset and the struct field suffix we just computed?
17189     if (!FitsIn<target_ssize_t>(fieldOffsets + arrayInfo->m_elemOffset) ||
17190         !FitsIn<target_ssize_t>(arrayInfo->m_elemSize))
17191     {
17192         // This seems unlikely, but no harm in being safe...
17193         *pInxVN = comp->GetValueNumStore()->VNForExpr(nullptr, TYP_INT);
17194         return;
17195     }
17196     // Otherwise...
17197     target_ssize_t offsetAccountedFor = static_cast<target_ssize_t>(fieldOffsets + arrayInfo->m_elemOffset);
17198     target_ssize_t elemSize           = static_cast<target_ssize_t>(arrayInfo->m_elemSize);
17199
17200     target_ssize_t constIndOffset = offset - offsetAccountedFor;
17201     // This should be divisible by the element size...
17202     assert((constIndOffset % elemSize) == 0);
17203     target_ssize_t constInd = constIndOffset / elemSize;
17204
17205     ValueNumStore* vnStore = comp->GetValueNumStore();
17206
17207     if (inxVN == ValueNumStore::NoVN)
17208     {
17209         // Must be a constant index.
17210         *pInxVN = vnStore->VNForPtrSizeIntCon(constInd);
17211     }
17212     else
17213     {
17214         //
17215         // Perform ((inxVN / elemSizeVN) + vnForConstInd)
17216         //
17217
17218         // The value associated with the index value number (inxVN) is the offset into the array,
17219         // which has been scaled by element size. We need to recover the array index from that offset
17220         if (vnStore->IsVNConstant(inxVN))
17221         {
17222             target_ssize_t index = vnStore->CoercedConstantValue<target_ssize_t>(inxVN);
17223             noway_assert(elemSize > 0 && ((index % elemSize) == 0));
17224             *pInxVN = vnStore->VNForPtrSizeIntCon((index / elemSize) + constInd);
17225         }
17226         else
17227         {
17228             bool canFoldDiv = false;
17229
17230             // If the index VN is a MUL by elemSize, see if we can eliminate it instead of adding
17231             // the division by elemSize.
17232             VNFuncApp funcApp;
17233             if (vnStore->GetVNFunc(inxVN, &funcApp) && funcApp.m_func == (VNFunc)GT_MUL)
17234             {
17235                 ValueNum vnForElemSize = vnStore->VNForLongCon(elemSize);
17236
17237                 // One of the multiply operand is elemSize, so the resulting
17238                 // index VN should simply be the other operand.
17239                 if (funcApp.m_args[1] == vnForElemSize)
17240                 {
17241                     *pInxVN    = funcApp.m_args[0];
17242                     canFoldDiv = true;
17243                 }
17244                 else if (funcApp.m_args[0] == vnForElemSize)
17245                 {
17246                     *pInxVN    = funcApp.m_args[1];
17247                     canFoldDiv = true;
17248                 }
17249             }
17250
17251             // Perform ((inxVN / elemSizeVN) + vnForConstInd)
17252             if (!canFoldDiv)
17253             {
17254                 ValueNum vnForElemSize = vnStore->VNForPtrSizeIntCon(elemSize);
17255                 ValueNum vnForScaledInx =
17256                     vnStore->VNForFunc(TYP_I_IMPL, GetVNFuncForOper(GT_DIV, VOK_Default), inxVN, vnForElemSize);
17257                 *pInxVN = vnForScaledInx;
17258             }
17259
17260             if (constInd != 0)
17261             {
17262                 ValueNum vnForConstInd = comp->GetValueNumStore()->VNForPtrSizeIntCon(constInd);
17263                 VNFunc   vnFunc        = GetVNFuncForOper(GT_ADD, VOK_Default);
17264
17265                 *pInxVN = comp->GetValueNumStore()->VNForFunc(TYP_I_IMPL, vnFunc, *pInxVN, vnForConstInd);
17266             }
17267         }
17268     }
17269 }
17270
17271 void GenTree::ParseArrayAddressWork(Compiler*       comp,
17272                                     target_ssize_t  inputMul,
17273                                     GenTree**       pArr,
17274                                     ValueNum*       pInxVN,
17275                                     target_ssize_t* pOffset,
17276                                     FieldSeqNode**  pFldSeq)
17277 {
17278     if (TypeGet() == TYP_REF)
17279     {
17280         // This must be the array pointer.
17281         *pArr = this;
17282         assert(inputMul == 1); // Can't multiply the array pointer by anything.
17283     }
17284     else
17285     {
17286         switch (OperGet())
17287         {
17288             case GT_CNS_INT:
17289                 *pFldSeq = comp->GetFieldSeqStore()->Append(*pFldSeq, gtIntCon.gtFieldSeq);
17290                 assert(!gtIntCon.ImmedValNeedsReloc(comp));
17291                 // TODO-CrossBitness: we wouldn't need the cast below if GenTreeIntCon::gtIconVal had target_ssize_t
17292                 // type.
17293                 *pOffset += (inputMul * (target_ssize_t)(gtIntCon.gtIconVal));
17294                 return;
17295
17296             case GT_ADD:
17297             case GT_SUB:
17298                 gtOp.gtOp1->ParseArrayAddressWork(comp, inputMul, pArr, pInxVN, pOffset, pFldSeq);
17299                 if (OperGet() == GT_SUB)
17300                 {
17301                     inputMul = -inputMul;
17302                 }
17303                 gtOp.gtOp2->ParseArrayAddressWork(comp, inputMul, pArr, pInxVN, pOffset, pFldSeq);
17304                 return;
17305
17306             case GT_MUL:
17307             {
17308                 // If one op is a constant, continue parsing down.
17309                 target_ssize_t subMul   = 0;
17310                 GenTree*       nonConst = nullptr;
17311                 if (gtOp.gtOp1->IsCnsIntOrI())
17312                 {
17313                     // If the other arg is an int constant, and is a "not-a-field", choose
17314                     // that as the multiplier, thus preserving constant index offsets...
17315                     if (gtOp.gtOp2->OperGet() == GT_CNS_INT &&
17316                         gtOp.gtOp2->gtIntCon.gtFieldSeq == FieldSeqStore::NotAField())
17317                     {
17318                         assert(!gtOp.gtOp2->gtIntCon.ImmedValNeedsReloc(comp));
17319                         // TODO-CrossBitness: we wouldn't need the cast below if GenTreeIntConCommon::gtIconVal had
17320                         // target_ssize_t type.
17321                         subMul   = (target_ssize_t)gtOp.gtOp2->gtIntConCommon.IconValue();
17322                         nonConst = gtOp.gtOp1;
17323                     }
17324                     else
17325                     {
17326                         assert(!gtOp.gtOp1->gtIntCon.ImmedValNeedsReloc(comp));
17327                         // TODO-CrossBitness: we wouldn't need the cast below if GenTreeIntConCommon::gtIconVal had
17328                         // target_ssize_t type.
17329                         subMul   = (target_ssize_t)gtOp.gtOp1->gtIntConCommon.IconValue();
17330                         nonConst = gtOp.gtOp2;
17331                     }
17332                 }
17333                 else if (gtOp.gtOp2->IsCnsIntOrI())
17334                 {
17335                     assert(!gtOp.gtOp2->gtIntCon.ImmedValNeedsReloc(comp));
17336                     // TODO-CrossBitness: we wouldn't need the cast below if GenTreeIntConCommon::gtIconVal had
17337                     // target_ssize_t type.
17338                     subMul   = (target_ssize_t)gtOp.gtOp2->gtIntConCommon.IconValue();
17339                     nonConst = gtOp.gtOp1;
17340                 }
17341                 if (nonConst != nullptr)
17342                 {
17343                     nonConst->ParseArrayAddressWork(comp, inputMul * subMul, pArr, pInxVN, pOffset, pFldSeq);
17344                     return;
17345                 }
17346                 // Otherwise, exit the switch, treat as a contribution to the index.
17347             }
17348             break;
17349
17350             case GT_LSH:
17351                 // If one op is a constant, continue parsing down.
17352                 if (gtOp.gtOp2->IsCnsIntOrI())
17353                 {
17354                     assert(!gtOp.gtOp2->gtIntCon.ImmedValNeedsReloc(comp));
17355                     // TODO-CrossBitness: we wouldn't need the cast below if GenTreeIntCon::gtIconVal had target_ssize_t
17356                     // type.
17357                     target_ssize_t subMul = target_ssize_t{1} << (target_ssize_t)gtOp.gtOp2->gtIntConCommon.IconValue();
17358                     gtOp.gtOp1->ParseArrayAddressWork(comp, inputMul * subMul, pArr, pInxVN, pOffset, pFldSeq);
17359                     return;
17360                 }
17361                 // Otherwise, exit the switch, treat as a contribution to the index.
17362                 break;
17363
17364             case GT_COMMA:
17365                 // We don't care about exceptions for this purpose.
17366                 if ((gtOp.gtOp1->OperGet() == GT_ARR_BOUNDS_CHECK) || gtOp.gtOp1->IsNothingNode())
17367                 {
17368                     gtOp.gtOp2->ParseArrayAddressWork(comp, inputMul, pArr, pInxVN, pOffset, pFldSeq);
17369                     return;
17370                 }
17371                 break;
17372
17373             default:
17374                 break;
17375         }
17376         // If we didn't return above, must be a contribution to the non-constant part of the index VN.
17377         ValueNum vn = comp->GetValueNumStore()->VNLiberalNormalValue(gtVNPair);
17378         if (inputMul != 1)
17379         {
17380             ValueNum mulVN = comp->GetValueNumStore()->VNForLongCon(inputMul);
17381             vn = comp->GetValueNumStore()->VNForFunc(TypeGet(), GetVNFuncForOper(GT_MUL, VOK_Default), mulVN, vn);
17382         }
17383         if (*pInxVN == ValueNumStore::NoVN)
17384         {
17385             *pInxVN = vn;
17386         }
17387         else
17388         {
17389             *pInxVN =
17390                 comp->GetValueNumStore()->VNForFunc(TypeGet(), GetVNFuncForOper(GT_ADD, VOK_Default), *pInxVN, vn);
17391         }
17392     }
17393 }
17394
17395 bool GenTree::ParseArrayElemForm(Compiler* comp, ArrayInfo* arrayInfo, FieldSeqNode** pFldSeq)
17396 {
17397     if (OperIsIndir())
17398     {
17399         if (gtFlags & GTF_IND_ARR_INDEX)
17400         {
17401             bool b = comp->GetArrayInfoMap()->Lookup(this, arrayInfo);
17402             assert(b);
17403             return true;
17404         }
17405
17406         // Otherwise...
17407         GenTree* addr = AsIndir()->Addr();
17408         return addr->ParseArrayElemAddrForm(comp, arrayInfo, pFldSeq);
17409     }
17410     else
17411     {
17412         return false;
17413     }
17414 }
17415
17416 bool GenTree::ParseArrayElemAddrForm(Compiler* comp, ArrayInfo* arrayInfo, FieldSeqNode** pFldSeq)
17417 {
17418     switch (OperGet())
17419     {
17420         case GT_ADD:
17421         {
17422             GenTree* arrAddr = nullptr;
17423             GenTree* offset  = nullptr;
17424             if (gtOp.gtOp1->TypeGet() == TYP_BYREF)
17425             {
17426                 arrAddr = gtOp.gtOp1;
17427                 offset  = gtOp.gtOp2;
17428             }
17429             else if (gtOp.gtOp2->TypeGet() == TYP_BYREF)
17430             {
17431                 arrAddr = gtOp.gtOp2;
17432                 offset  = gtOp.gtOp1;
17433             }
17434             else
17435             {
17436                 return false;
17437             }
17438             if (!offset->ParseOffsetForm(comp, pFldSeq))
17439             {
17440                 return false;
17441             }
17442             return arrAddr->ParseArrayElemAddrForm(comp, arrayInfo, pFldSeq);
17443         }
17444
17445         case GT_ADDR:
17446         {
17447             GenTree* addrArg = gtOp.gtOp1;
17448             if (addrArg->OperGet() != GT_IND)
17449             {
17450                 return false;
17451             }
17452             else
17453             {
17454                 // The "Addr" node might be annotated with a zero-offset field sequence.
17455                 FieldSeqNode* zeroOffsetFldSeq = nullptr;
17456                 if (comp->GetZeroOffsetFieldMap()->Lookup(this, &zeroOffsetFldSeq))
17457                 {
17458                     *pFldSeq = comp->GetFieldSeqStore()->Append(*pFldSeq, zeroOffsetFldSeq);
17459                 }
17460                 return addrArg->ParseArrayElemForm(comp, arrayInfo, pFldSeq);
17461             }
17462         }
17463
17464         default:
17465             return false;
17466     }
17467 }
17468
17469 bool GenTree::ParseOffsetForm(Compiler* comp, FieldSeqNode** pFldSeq)
17470 {
17471     switch (OperGet())
17472     {
17473         case GT_CNS_INT:
17474         {
17475             GenTreeIntCon* icon = AsIntCon();
17476             *pFldSeq            = comp->GetFieldSeqStore()->Append(*pFldSeq, icon->gtFieldSeq);
17477             return true;
17478         }
17479
17480         case GT_ADD:
17481             if (!gtOp.gtOp1->ParseOffsetForm(comp, pFldSeq))
17482             {
17483                 return false;
17484             }
17485             return gtOp.gtOp2->ParseOffsetForm(comp, pFldSeq);
17486
17487         default:
17488             return false;
17489     }
17490 }
17491
17492 void GenTree::LabelIndex(Compiler* comp, bool isConst)
17493 {
17494     switch (OperGet())
17495     {
17496         case GT_CNS_INT:
17497             // If we got here, this is a contribution to the constant part of the index.
17498             if (isConst)
17499             {
17500                 gtIntCon.gtFieldSeq =
17501                     comp->GetFieldSeqStore()->CreateSingleton(FieldSeqStore::ConstantIndexPseudoField);
17502             }
17503             return;
17504
17505         case GT_LCL_VAR:
17506             gtFlags |= GTF_VAR_ARR_INDEX;
17507             return;
17508
17509         case GT_ADD:
17510         case GT_SUB:
17511             gtOp.gtOp1->LabelIndex(comp, isConst);
17512             gtOp.gtOp2->LabelIndex(comp, isConst);
17513             break;
17514
17515         case GT_CAST:
17516             gtOp.gtOp1->LabelIndex(comp, isConst);
17517             break;
17518
17519         case GT_ARR_LENGTH:
17520             gtFlags |= GTF_ARRLEN_ARR_IDX;
17521             return;
17522
17523         default:
17524             // For all other operators, peel off one constant; and then label the other if it's also a constant.
17525             if (OperIsArithmetic() || OperIsCompare())
17526             {
17527                 if (gtOp.gtOp2->OperGet() == GT_CNS_INT)
17528                 {
17529                     gtOp.gtOp1->LabelIndex(comp, isConst);
17530                     break;
17531                 }
17532                 else if (gtOp.gtOp1->OperGet() == GT_CNS_INT)
17533                 {
17534                     gtOp.gtOp2->LabelIndex(comp, isConst);
17535                     break;
17536                 }
17537                 // Otherwise continue downward on both, labeling vars.
17538                 gtOp.gtOp1->LabelIndex(comp, false);
17539                 gtOp.gtOp2->LabelIndex(comp, false);
17540             }
17541             break;
17542     }
17543 }
17544
17545 // Note that the value of the below field doesn't matter; it exists only to provide a distinguished address.
17546 //
17547 // static
17548 FieldSeqNode FieldSeqStore::s_notAField(nullptr, nullptr);
17549
17550 // FieldSeqStore methods.
17551 FieldSeqStore::FieldSeqStore(CompAllocator alloc) : m_alloc(alloc), m_canonMap(new (alloc) FieldSeqNodeCanonMap(alloc))
17552 {
17553 }
17554
17555 FieldSeqNode* FieldSeqStore::CreateSingleton(CORINFO_FIELD_HANDLE fieldHnd)
17556 {
17557     FieldSeqNode  fsn(fieldHnd, nullptr);
17558     FieldSeqNode* res = nullptr;
17559     if (m_canonMap->Lookup(fsn, &res))
17560     {
17561         return res;
17562     }
17563     else
17564     {
17565         res  = m_alloc.allocate<FieldSeqNode>(1);
17566         *res = fsn;
17567         m_canonMap->Set(fsn, res);
17568         return res;
17569     }
17570 }
17571
17572 FieldSeqNode* FieldSeqStore::Append(FieldSeqNode* a, FieldSeqNode* b)
17573 {
17574     if (a == nullptr)
17575     {
17576         return b;
17577     }
17578     else if (a == NotAField())
17579     {
17580         return NotAField();
17581     }
17582     else if (b == nullptr)
17583     {
17584         return a;
17585     }
17586     else if (b == NotAField())
17587     {
17588         return NotAField();
17589         // Extremely special case for ConstantIndex pseudo-fields -- appending consecutive such
17590         // together collapse to one.
17591     }
17592     else if (a->m_next == nullptr && a->m_fieldHnd == ConstantIndexPseudoField &&
17593              b->m_fieldHnd == ConstantIndexPseudoField)
17594     {
17595         return b;
17596     }
17597     else
17598     {
17599         FieldSeqNode* tmp = Append(a->m_next, b);
17600         FieldSeqNode  fsn(a->m_fieldHnd, tmp);
17601         FieldSeqNode* res = nullptr;
17602         if (m_canonMap->Lookup(fsn, &res))
17603         {
17604             return res;
17605         }
17606         else
17607         {
17608             res  = m_alloc.allocate<FieldSeqNode>(1);
17609             *res = fsn;
17610             m_canonMap->Set(fsn, res);
17611             return res;
17612         }
17613     }
17614 }
17615
17616 // Static vars.
17617 int FieldSeqStore::FirstElemPseudoFieldStruct;
17618 int FieldSeqStore::ConstantIndexPseudoFieldStruct;
17619
17620 CORINFO_FIELD_HANDLE FieldSeqStore::FirstElemPseudoField =
17621     (CORINFO_FIELD_HANDLE)&FieldSeqStore::FirstElemPseudoFieldStruct;
17622 CORINFO_FIELD_HANDLE FieldSeqStore::ConstantIndexPseudoField =
17623     (CORINFO_FIELD_HANDLE)&FieldSeqStore::ConstantIndexPseudoFieldStruct;
17624
17625 bool FieldSeqNode::IsFirstElemFieldSeq()
17626 {
17627     // this must be non-null per ISO C++
17628     return m_fieldHnd == FieldSeqStore::FirstElemPseudoField;
17629 }
17630
17631 bool FieldSeqNode::IsConstantIndexFieldSeq()
17632 {
17633     // this must be non-null per ISO C++
17634     return m_fieldHnd == FieldSeqStore::ConstantIndexPseudoField;
17635 }
17636
17637 bool FieldSeqNode::IsPseudoField()
17638 {
17639     if (this == nullptr)
17640     {
17641         return false;
17642     }
17643     return m_fieldHnd == FieldSeqStore::FirstElemPseudoField || m_fieldHnd == FieldSeqStore::ConstantIndexPseudoField;
17644 }
17645
17646 #ifdef FEATURE_SIMD
17647 GenTreeSIMD* Compiler::gtNewSIMDNode(
17648     var_types type, GenTree* op1, SIMDIntrinsicID simdIntrinsicID, var_types baseType, unsigned size)
17649 {
17650     assert(op1 != nullptr);
17651     SetOpLclRelatedToSIMDIntrinsic(op1);
17652
17653     return new (this, GT_SIMD) GenTreeSIMD(type, op1, simdIntrinsicID, baseType, size);
17654 }
17655
17656 GenTreeSIMD* Compiler::gtNewSIMDNode(
17657     var_types type, GenTree* op1, GenTree* op2, SIMDIntrinsicID simdIntrinsicID, var_types baseType, unsigned size)
17658 {
17659     assert(op1 != nullptr);
17660     SetOpLclRelatedToSIMDIntrinsic(op1);
17661     SetOpLclRelatedToSIMDIntrinsic(op2);
17662
17663     return new (this, GT_SIMD) GenTreeSIMD(type, op1, op2, simdIntrinsicID, baseType, size);
17664 }
17665
17666 //-------------------------------------------------------------------
17667 // SetOpLclRelatedToSIMDIntrinsic: Determine if the tree has a local var that needs to be set
17668 // as used by a SIMD intrinsic, and if so, set that local var appropriately.
17669 //
17670 // Arguments:
17671 //     op - The tree, to be an operand of a new GT_SIMD node, to check.
17672 //
17673 void Compiler::SetOpLclRelatedToSIMDIntrinsic(GenTree* op)
17674 {
17675     if (op != nullptr)
17676     {
17677         if (op->OperIsLocal())
17678         {
17679             setLclRelatedToSIMDIntrinsic(op);
17680         }
17681         else if ((op->OperGet() == GT_OBJ) && (op->gtOp.gtOp1->OperGet() == GT_ADDR) &&
17682                  op->gtOp.gtOp1->gtOp.gtOp1->OperIsLocal())
17683         {
17684             setLclRelatedToSIMDIntrinsic(op->gtOp.gtOp1->gtOp.gtOp1);
17685         }
17686     }
17687 }
17688
17689 bool GenTree::isCommutativeSIMDIntrinsic()
17690 {
17691     assert(gtOper == GT_SIMD);
17692     switch (AsSIMD()->gtSIMDIntrinsicID)
17693     {
17694         case SIMDIntrinsicAdd:
17695         case SIMDIntrinsicBitwiseAnd:
17696         case SIMDIntrinsicBitwiseOr:
17697         case SIMDIntrinsicBitwiseXor:
17698         case SIMDIntrinsicEqual:
17699         case SIMDIntrinsicMax:
17700         case SIMDIntrinsicMin:
17701         case SIMDIntrinsicMul:
17702         case SIMDIntrinsicOpEquality:
17703         case SIMDIntrinsicOpInEquality:
17704             return true;
17705         default:
17706             return false;
17707     }
17708 }
17709 #endif // FEATURE_SIMD
17710
17711 #ifdef FEATURE_HW_INTRINSICS
17712 bool GenTree::isCommutativeHWIntrinsic() const
17713 {
17714     assert(gtOper == GT_HWIntrinsic);
17715
17716 #ifdef _TARGET_XARCH_
17717     return HWIntrinsicInfo::IsCommutative(AsHWIntrinsic()->gtHWIntrinsicId);
17718 #else
17719     return false;
17720 #endif // _TARGET_XARCH_
17721 }
17722
17723 bool GenTree::isContainableHWIntrinsic() const
17724 {
17725     assert(gtOper == GT_HWIntrinsic);
17726
17727 #ifdef _TARGET_XARCH_
17728     switch (AsHWIntrinsic()->gtHWIntrinsicId)
17729     {
17730         case NI_SSE_LoadAlignedVector128:
17731         case NI_SSE_LoadScalarVector128:
17732         case NI_SSE_LoadVector128:
17733         case NI_SSE2_LoadAlignedVector128:
17734         case NI_SSE2_LoadScalarVector128:
17735         case NI_SSE2_LoadVector128:
17736         case NI_AVX_LoadAlignedVector256:
17737         case NI_AVX_LoadVector256:
17738         {
17739             return true;
17740         }
17741
17742         default:
17743         {
17744             return false;
17745         }
17746     }
17747 #else
17748     return false;
17749 #endif // _TARGET_XARCH_
17750 }
17751
17752 bool GenTree::isRMWHWIntrinsic(Compiler* comp)
17753 {
17754     assert(gtOper == GT_HWIntrinsic);
17755     assert(comp != nullptr);
17756
17757 #ifdef _TARGET_XARCH_
17758     if (!comp->canUseVexEncoding())
17759     {
17760         return HWIntrinsicInfo::HasRMWSemantics(AsHWIntrinsic()->gtHWIntrinsicId);
17761     }
17762
17763     switch (AsHWIntrinsic()->gtHWIntrinsicId)
17764     {
17765         // TODO-XArch-Cleanup: Move this switch block to be table driven.
17766
17767         case NI_SSE42_Crc32:
17768         case NI_SSE42_X64_Crc32:
17769         case NI_FMA_MultiplyAdd:
17770         case NI_FMA_MultiplyAddNegated:
17771         case NI_FMA_MultiplyAddNegatedScalar:
17772         case NI_FMA_MultiplyAddScalar:
17773         case NI_FMA_MultiplyAddSubtract:
17774         case NI_FMA_MultiplySubtract:
17775         case NI_FMA_MultiplySubtractAdd:
17776         case NI_FMA_MultiplySubtractNegated:
17777         case NI_FMA_MultiplySubtractNegatedScalar:
17778         case NI_FMA_MultiplySubtractScalar:
17779         {
17780             return true;
17781         }
17782
17783         default:
17784         {
17785             return false;
17786         }
17787     }
17788 #else
17789     return false;
17790 #endif // _TARGET_XARCH_
17791 }
17792
17793 GenTreeHWIntrinsic* Compiler::gtNewSimdHWIntrinsicNode(var_types      type,
17794                                                        NamedIntrinsic hwIntrinsicID,
17795                                                        var_types      baseType,
17796                                                        unsigned       size)
17797 {
17798     return new (this, GT_HWIntrinsic) GenTreeHWIntrinsic(type, hwIntrinsicID, baseType, size);
17799 }
17800
17801 GenTreeHWIntrinsic* Compiler::gtNewSimdHWIntrinsicNode(
17802     var_types type, GenTree* op1, NamedIntrinsic hwIntrinsicID, var_types baseType, unsigned simdSize)
17803 {
17804     SetOpLclRelatedToSIMDIntrinsic(op1);
17805
17806     return new (this, GT_HWIntrinsic) GenTreeHWIntrinsic(type, op1, hwIntrinsicID, baseType, simdSize);
17807 }
17808
17809 GenTreeHWIntrinsic* Compiler::gtNewSimdHWIntrinsicNode(
17810     var_types type, GenTree* op1, GenTree* op2, NamedIntrinsic hwIntrinsicID, var_types baseType, unsigned simdSize)
17811 {
17812     SetOpLclRelatedToSIMDIntrinsic(op1);
17813     SetOpLclRelatedToSIMDIntrinsic(op2);
17814
17815     return new (this, GT_HWIntrinsic) GenTreeHWIntrinsic(type, op1, op2, hwIntrinsicID, baseType, simdSize);
17816 }
17817
17818 GenTreeHWIntrinsic* Compiler::gtNewSimdHWIntrinsicNode(var_types      type,
17819                                                        GenTree*       op1,
17820                                                        GenTree*       op2,
17821                                                        GenTree*       op3,
17822                                                        NamedIntrinsic hwIntrinsicID,
17823                                                        var_types      baseType,
17824                                                        unsigned       size)
17825 {
17826     SetOpLclRelatedToSIMDIntrinsic(op1);
17827     SetOpLclRelatedToSIMDIntrinsic(op2);
17828     SetOpLclRelatedToSIMDIntrinsic(op3);
17829
17830     return new (this, GT_HWIntrinsic)
17831         GenTreeHWIntrinsic(type, gtNewArgList(op1, op2, op3), hwIntrinsicID, baseType, size);
17832 }
17833
17834 GenTreeHWIntrinsic* Compiler::gtNewSimdHWIntrinsicNode(var_types      type,
17835                                                        GenTree*       op1,
17836                                                        GenTree*       op2,
17837                                                        GenTree*       op3,
17838                                                        GenTree*       op4,
17839                                                        NamedIntrinsic hwIntrinsicID,
17840                                                        var_types      baseType,
17841                                                        unsigned       size)
17842 {
17843     SetOpLclRelatedToSIMDIntrinsic(op1);
17844     SetOpLclRelatedToSIMDIntrinsic(op2);
17845     SetOpLclRelatedToSIMDIntrinsic(op3);
17846     SetOpLclRelatedToSIMDIntrinsic(op4);
17847
17848     return new (this, GT_HWIntrinsic)
17849         GenTreeHWIntrinsic(type, gtNewArgList(op1, op2, op3, op4), hwIntrinsicID, baseType, size);
17850 }
17851
17852 GenTreeHWIntrinsic* Compiler::gtNewScalarHWIntrinsicNode(var_types type, GenTree* op1, NamedIntrinsic hwIntrinsicID)
17853 {
17854     SetOpLclRelatedToSIMDIntrinsic(op1);
17855
17856     return new (this, GT_HWIntrinsic) GenTreeHWIntrinsic(type, op1, hwIntrinsicID, TYP_UNKNOWN, 0);
17857 }
17858
17859 GenTreeHWIntrinsic* Compiler::gtNewScalarHWIntrinsicNode(var_types      type,
17860                                                          GenTree*       op1,
17861                                                          GenTree*       op2,
17862                                                          NamedIntrinsic hwIntrinsicID)
17863 {
17864     SetOpLclRelatedToSIMDIntrinsic(op1);
17865     SetOpLclRelatedToSIMDIntrinsic(op2);
17866
17867     return new (this, GT_HWIntrinsic) GenTreeHWIntrinsic(type, op1, op2, hwIntrinsicID, TYP_UNKNOWN, 0);
17868 }
17869
17870 GenTreeHWIntrinsic* Compiler::gtNewScalarHWIntrinsicNode(
17871     var_types type, GenTree* op1, GenTree* op2, GenTree* op3, NamedIntrinsic hwIntrinsicID)
17872 {
17873     SetOpLclRelatedToSIMDIntrinsic(op1);
17874     SetOpLclRelatedToSIMDIntrinsic(op2);
17875     SetOpLclRelatedToSIMDIntrinsic(op3);
17876
17877     return new (this, GT_HWIntrinsic)
17878         GenTreeHWIntrinsic(type, gtNewArgList(op1, op2, op3), hwIntrinsicID, TYP_UNKNOWN, 0);
17879 }
17880
17881 //---------------------------------------------------------------------------------------
17882 // gtNewMustThrowException:
17883 //    create a throw node (calling into JIT helper) that must be thrown.
17884 //    The result would be a comma node: COMMA(jithelperthrow(void), x) where x's type should be specified.
17885 //
17886 // Arguments
17887 //    helper      -  JIT helper ID
17888 //    type        -  return type of the node
17889 //
17890 // Return Value
17891 //    pointer to the throw node
17892 //
17893 GenTree* Compiler::gtNewMustThrowException(unsigned helper, var_types type, CORINFO_CLASS_HANDLE clsHnd)
17894 {
17895     GenTreeCall* node = gtNewHelperCallNode(helper, TYP_VOID);
17896     node->gtCallMoreFlags |= GTF_CALL_M_DOES_NOT_RETURN;
17897     if (type != TYP_VOID)
17898     {
17899         unsigned dummyTemp = lvaGrabTemp(true DEBUGARG("dummy temp of must thrown exception"));
17900         if (type == TYP_STRUCT)
17901         {
17902             lvaSetStruct(dummyTemp, clsHnd, false);
17903             type = lvaTable[dummyTemp].lvType; // struct type is normalized
17904         }
17905         else
17906         {
17907             lvaTable[dummyTemp].lvType = type;
17908         }
17909         GenTree* dummyNode = gtNewLclvNode(dummyTemp, type);
17910         return gtNewOperNode(GT_COMMA, type, node, dummyNode);
17911     }
17912     return node;
17913 }
17914
17915 // Returns true for the HW Instrinsic instructions that have MemoryLoad semantics, false otherwise
17916 bool GenTreeHWIntrinsic::OperIsMemoryLoad()
17917 {
17918 #ifdef _TARGET_XARCH_
17919     // Some xarch instructions have MemoryLoad sematics
17920     HWIntrinsicCategory category = HWIntrinsicInfo::lookupCategory(gtHWIntrinsicId);
17921     if (category == HW_Category_MemoryLoad)
17922     {
17923         return true;
17924     }
17925     else if (HWIntrinsicInfo::MaybeMemoryLoad(gtHWIntrinsicId))
17926     {
17927         // Some AVX intrinsic (without HW_Category_MemoryLoad) also have MemoryLoad semantics
17928         if (category == HW_Category_SIMDScalar)
17929         {
17930             // Avx2.BroadcastScalarToVector128/256 have vector and pointer overloads both, e.g.,
17931             // Vector128<byte> BroadcastScalarToVector128(Vector128<byte> value)
17932             // Vector128<byte> BroadcastScalarToVector128(byte* source)
17933             // So, we need to check the argument's type is memory-reference (TYP_I_IMPL) or not
17934             assert(HWIntrinsicInfo::lookupNumArgs(this) == 1);
17935             return (gtHWIntrinsicId == NI_AVX2_BroadcastScalarToVector128 ||
17936                     gtHWIntrinsicId == NI_AVX2_BroadcastScalarToVector256) &&
17937                    gtOp.gtOp1->TypeGet() == TYP_I_IMPL;
17938         }
17939         else if (category == HW_Category_IMM)
17940         {
17941             // Do we have less than 3 operands?
17942             if (HWIntrinsicInfo::lookupNumArgs(this) < 3)
17943             {
17944                 return false;
17945             }
17946             else // We have 3 or more operands/args
17947             {
17948                 // All the Avx2.Gather* are "load" instructions
17949                 if (HWIntrinsicInfo::isAVX2GatherIntrinsic(gtHWIntrinsicId))
17950                 {
17951                     return true;
17952                 }
17953
17954                 GenTreeArgList* argList = gtOp.gtOp1->AsArgList();
17955
17956                 // Avx/Avx2.InsertVector128 have vector and pointer overloads both, e.g.,
17957                 // Vector256<sbyte> InsertVector128(Vector256<sbyte> value, Vector128<sbyte> data, byte index)
17958                 // Vector256<sbyte> InsertVector128(Vector256<sbyte> value, sbyte* address, byte index)
17959                 // So, we need to check the second argument's type is memory-reference (TYP_I_IMPL) or not
17960                 if ((gtHWIntrinsicId == NI_AVX_InsertVector128 || gtHWIntrinsicId == NI_AVX2_InsertVector128) &&
17961                     (argList->Rest()->Current()->TypeGet() == TYP_I_IMPL)) // Is the type of the second arg TYP_I_IMPL?
17962                 {
17963                     // This is Avx/Avx2.InsertVector128
17964                     return true;
17965                 }
17966             }
17967         }
17968     }
17969 #endif // _TARGET_XARCH_
17970     return false;
17971 }
17972
17973 // Returns true for the HW Instrinsic instructions that have MemoryStore semantics, false otherwise
17974 bool GenTreeHWIntrinsic::OperIsMemoryStore()
17975 {
17976 #ifdef _TARGET_XARCH_
17977     // Some xarch instructions have MemoryStore sematics
17978     HWIntrinsicCategory category = HWIntrinsicInfo::lookupCategory(gtHWIntrinsicId);
17979     if (category == HW_Category_MemoryStore)
17980     {
17981         return true;
17982     }
17983     else if (HWIntrinsicInfo::MaybeMemoryStore(gtHWIntrinsicId) &&
17984              (category == HW_Category_IMM || category == HW_Category_Scalar))
17985     {
17986         // Some AVX intrinsic (without HW_Category_MemoryStore) also have MemoryStore semantics
17987
17988         // Avx/Avx2.InsertVector128 have vector and pointer overloads both, e.g.,
17989         // Vector128<sbyte> ExtractVector128(Vector256<sbyte> value, byte index)
17990         // void ExtractVector128(sbyte* address, Vector256<sbyte> value, byte index)
17991         // Bmi2/Bmi2.X64.MultiplyNoFlags may return the lower half result by a out argument
17992         // unsafe ulong MultiplyNoFlags(ulong left, ulong right, ulong* low)
17993         //
17994         // So, the 3-argument form is MemoryStore
17995         if (HWIntrinsicInfo::lookupNumArgs(this) == 3)
17996         {
17997             switch (gtHWIntrinsicId)
17998             {
17999                 case NI_AVX_ExtractVector128:
18000                 case NI_AVX2_ExtractVector128:
18001                 case NI_BMI2_MultiplyNoFlags:
18002                 case NI_BMI2_X64_MultiplyNoFlags:
18003                     return true;
18004                 default:
18005                     return false;
18006             }
18007         }
18008     }
18009 #endif // _TARGET_XARCH_
18010     return false;
18011 }
18012
18013 // Returns true for the HW Instrinsic instructions that have MemoryLoad semantics, false otherwise
18014 bool GenTreeHWIntrinsic::OperIsMemoryLoadOrStore()
18015 {
18016 #ifdef _TARGET_XARCH_
18017     return OperIsMemoryLoad() || OperIsMemoryStore();
18018 #endif // _TARGET_XARCH_
18019     return false;
18020 }
18021
18022 #endif // FEATURE_HW_INTRINSICS
18023
18024 //---------------------------------------------------------------------------------------
18025 // InitializeStructReturnType:
18026 //    Initialize the Return Type Descriptor for a method that returns a struct type
18027 //
18028 // Arguments
18029 //    comp        -  Compiler Instance
18030 //    retClsHnd   -  VM handle to the struct type returned by the method
18031 //
18032 // Return Value
18033 //    None
18034 //
18035 void ReturnTypeDesc::InitializeStructReturnType(Compiler* comp, CORINFO_CLASS_HANDLE retClsHnd)
18036 {
18037     assert(!m_inited);
18038
18039 #if FEATURE_MULTIREG_RET
18040
18041     assert(retClsHnd != NO_CLASS_HANDLE);
18042     unsigned structSize = comp->info.compCompHnd->getClassSize(retClsHnd);
18043
18044     Compiler::structPassingKind howToReturnStruct;
18045     var_types                   returnType = comp->getReturnTypeForStruct(retClsHnd, &howToReturnStruct, structSize);
18046
18047     switch (howToReturnStruct)
18048     {
18049         case Compiler::SPK_EnclosingType:
18050             m_isEnclosingType = true;
18051             __fallthrough;
18052
18053         case Compiler::SPK_PrimitiveType:
18054         {
18055             assert(returnType != TYP_UNKNOWN);
18056             assert(!varTypeIsStruct(returnType));
18057             m_regType[0] = returnType;
18058             break;
18059         }
18060
18061         case Compiler::SPK_ByValueAsHfa:
18062         {
18063             assert(varTypeIsStruct(returnType));
18064             var_types hfaType = comp->GetHfaType(retClsHnd);
18065
18066             // We should have an hfa struct type
18067             assert(varTypeIsFloating(hfaType));
18068
18069             // Note that the retail build issues a warning about a potential divsion by zero without this Max function
18070             unsigned elemSize = Max((unsigned)1, EA_SIZE_IN_BYTES(emitActualTypeSize(hfaType)));
18071
18072             // The size of this struct should be evenly divisible by elemSize
18073             assert((structSize % elemSize) == 0);
18074
18075             unsigned hfaCount = (structSize / elemSize);
18076             for (unsigned i = 0; i < hfaCount; ++i)
18077             {
18078                 m_regType[i] = hfaType;
18079             }
18080
18081             if (comp->compFloatingPointUsed == false)
18082             {
18083                 comp->compFloatingPointUsed = true;
18084             }
18085             break;
18086         }
18087
18088         case Compiler::SPK_ByValue:
18089         {
18090             assert(varTypeIsStruct(returnType));
18091
18092 #ifdef UNIX_AMD64_ABI
18093
18094             SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR structDesc;
18095             comp->eeGetSystemVAmd64PassStructInRegisterDescriptor(retClsHnd, &structDesc);
18096
18097             assert(structDesc.passedInRegisters);
18098             for (int i = 0; i < structDesc.eightByteCount; i++)
18099             {
18100                 assert(i < MAX_RET_REG_COUNT);
18101                 m_regType[i] = comp->GetEightByteType(structDesc, i);
18102             }
18103
18104 #elif defined(_TARGET_ARM64_)
18105
18106             // a non-HFA struct returned using two registers
18107             //
18108             assert((structSize > TARGET_POINTER_SIZE) && (structSize <= (2 * TARGET_POINTER_SIZE)));
18109
18110             BYTE gcPtrs[2] = {TYPE_GC_NONE, TYPE_GC_NONE};
18111             comp->info.compCompHnd->getClassGClayout(retClsHnd, &gcPtrs[0]);
18112             for (unsigned i = 0; i < 2; ++i)
18113             {
18114                 m_regType[i] = comp->getJitGCType(gcPtrs[i]);
18115             }
18116
18117 #else //  _TARGET_XXX_
18118
18119             // This target needs support here!
18120             //
18121             NYI("Unsupported TARGET returning a TYP_STRUCT in InitializeStructReturnType");
18122
18123 #endif // UNIX_AMD64_ABI
18124
18125             break; // for case SPK_ByValue
18126         }
18127
18128         case Compiler::SPK_ByReference:
18129
18130             // We are returning using the return buffer argument
18131             // There are no return registers
18132             break;
18133
18134         default:
18135
18136             unreached(); // By the contract of getReturnTypeForStruct we should never get here.
18137
18138     } // end of switch (howToReturnStruct)
18139
18140 #endif //  FEATURE_MULTIREG_RET
18141
18142 #ifdef DEBUG
18143     m_inited = true;
18144 #endif
18145 }
18146
18147 //---------------------------------------------------------------------------------------
18148 // InitializeLongReturnType:
18149 //    Initialize the Return Type Descriptor for a method that returns a TYP_LONG
18150 //
18151 // Arguments
18152 //    comp        -  Compiler Instance
18153 //
18154 // Return Value
18155 //    None
18156 //
18157 void ReturnTypeDesc::InitializeLongReturnType(Compiler* comp)
18158 {
18159 #if defined(_TARGET_X86_) || defined(_TARGET_ARM_)
18160
18161     // Setups up a ReturnTypeDesc for returning a long using two registers
18162     //
18163     assert(MAX_RET_REG_COUNT >= 2);
18164     m_regType[0] = TYP_INT;
18165     m_regType[1] = TYP_INT;
18166
18167 #else // not (_TARGET_X86_ or _TARGET_ARM_)
18168
18169     m_regType[0] = TYP_LONG;
18170
18171 #endif // _TARGET_X86_ or _TARGET_ARM_
18172
18173 #ifdef DEBUG
18174     m_inited = true;
18175 #endif
18176 }
18177
18178 //-------------------------------------------------------------------
18179 // GetABIReturnReg:  Return ith return register as per target ABI
18180 //
18181 // Arguments:
18182 //     idx   -   Index of the return register.
18183 //               The first return register has an index of 0 and so on.
18184 //
18185 // Return Value:
18186 //     Returns ith return register as per target ABI.
18187 //
18188 // Notes:
18189 //     x86 and ARM return long in multiple registers.
18190 //     ARM and ARM64 return HFA struct in multiple registers.
18191 //
18192 regNumber ReturnTypeDesc::GetABIReturnReg(unsigned idx)
18193 {
18194     unsigned count = GetReturnRegCount();
18195     assert(idx < count);
18196
18197     regNumber resultReg = REG_NA;
18198
18199 #ifdef UNIX_AMD64_ABI
18200     var_types regType0 = GetReturnRegType(0);
18201
18202     if (idx == 0)
18203     {
18204         if (varTypeIsIntegralOrI(regType0))
18205         {
18206             resultReg = REG_INTRET;
18207         }
18208         else
18209         {
18210             noway_assert(varTypeIsFloating(regType0));
18211             resultReg = REG_FLOATRET;
18212         }
18213     }
18214     else if (idx == 1)
18215     {
18216         var_types regType1 = GetReturnRegType(1);
18217
18218         if (varTypeIsIntegralOrI(regType1))
18219         {
18220             if (varTypeIsIntegralOrI(regType0))
18221             {
18222                 resultReg = REG_INTRET_1;
18223             }
18224             else
18225             {
18226                 resultReg = REG_INTRET;
18227             }
18228         }
18229         else
18230         {
18231             noway_assert(varTypeIsFloating(regType1));
18232
18233             if (varTypeIsFloating(regType0))
18234             {
18235                 resultReg = REG_FLOATRET_1;
18236             }
18237             else
18238             {
18239                 resultReg = REG_FLOATRET;
18240             }
18241         }
18242     }
18243
18244 #elif defined(_TARGET_X86_)
18245
18246     if (idx == 0)
18247     {
18248         resultReg = REG_LNGRET_LO;
18249     }
18250     else if (idx == 1)
18251     {
18252         resultReg = REG_LNGRET_HI;
18253     }
18254
18255 #elif defined(_TARGET_ARM_)
18256
18257     var_types regType = GetReturnRegType(idx);
18258     if (varTypeIsIntegralOrI(regType))
18259     {
18260         // Ints are returned in one return register.
18261         // Longs are returned in two return registers.
18262         if (idx == 0)
18263         {
18264             resultReg = REG_LNGRET_LO;
18265         }
18266         else if (idx == 1)
18267         {
18268             resultReg = REG_LNGRET_HI;
18269         }
18270     }
18271     else
18272     {
18273         // Floats are returned in one return register (f0).
18274         // Doubles are returned in one return register (d0).
18275         // Structs are returned in four registers with HFAs.
18276         assert(idx < MAX_RET_REG_COUNT); // Up to 4 return registers for HFA's
18277         if (regType == TYP_DOUBLE)
18278         {
18279             resultReg = (regNumber)((unsigned)(REG_FLOATRET) + idx * 2); // d0, d1, d2 or d3
18280         }
18281         else
18282         {
18283             resultReg = (regNumber)((unsigned)(REG_FLOATRET) + idx); // f0, f1, f2 or f3
18284         }
18285     }
18286
18287 #elif defined(_TARGET_ARM64_)
18288
18289     var_types regType = GetReturnRegType(idx);
18290     if (varTypeIsIntegralOrI(regType))
18291     {
18292         noway_assert(idx < 2);                              // Up to 2 return registers for 16-byte structs
18293         resultReg = (idx == 0) ? REG_INTRET : REG_INTRET_1; // X0 or X1
18294     }
18295     else
18296     {
18297         noway_assert(idx < 4);                                   // Up to 4 return registers for HFA's
18298         resultReg = (regNumber)((unsigned)(REG_FLOATRET) + idx); // V0, V1, V2 or V3
18299     }
18300
18301 #endif // TARGET_XXX
18302
18303     assert(resultReg != REG_NA);
18304     return resultReg;
18305 }
18306
18307 //--------------------------------------------------------------------------------
18308 // GetABIReturnRegs: get the mask of return registers as per target arch ABI.
18309 //
18310 // Arguments:
18311 //    None
18312 //
18313 // Return Value:
18314 //    reg mask of return registers in which the return type is returned.
18315 //
18316 // Note:
18317 //    This routine can be used when the caller is not particular about the order
18318 //    of return registers and wants to know the set of return registers.
18319 //
18320 // static
18321 regMaskTP ReturnTypeDesc::GetABIReturnRegs()
18322 {
18323     regMaskTP resultMask = RBM_NONE;
18324
18325     unsigned count = GetReturnRegCount();
18326     for (unsigned i = 0; i < count; ++i)
18327     {
18328         resultMask |= genRegMask(GetABIReturnReg(i));
18329     }
18330
18331     return resultMask;
18332 }
18333
18334 //------------------------------------------------------------------------
18335 // The following functions manage the gtRsvdRegs set of temporary registers
18336 // created by LSRA during code generation.
18337
18338 //------------------------------------------------------------------------
18339 // AvailableTempRegCount: return the number of available temporary registers in the (optional) given set
18340 // (typically, RBM_ALLINT or RBM_ALLFLOAT).
18341 //
18342 // Arguments:
18343 //    mask - (optional) Check for available temporary registers only in this set.
18344 //
18345 // Return Value:
18346 //    Count of available temporary registers in given set.
18347 //
18348 unsigned GenTree::AvailableTempRegCount(regMaskTP mask /* = (regMaskTP)-1 */) const
18349 {
18350     return genCountBits(gtRsvdRegs & mask);
18351 }
18352
18353 //------------------------------------------------------------------------
18354 // GetSingleTempReg: There is expected to be exactly one available temporary register
18355 // in the given mask in the gtRsvdRegs set. Get that register. No future calls to get
18356 // a temporary register are expected. Removes the register from the set, but only in
18357 // DEBUG to avoid doing unnecessary work in non-DEBUG builds.
18358 //
18359 // Arguments:
18360 //    mask - (optional) Get an available temporary register only in this set.
18361 //
18362 // Return Value:
18363 //    Available temporary register in given mask.
18364 //
18365 regNumber GenTree::GetSingleTempReg(regMaskTP mask /* = (regMaskTP)-1 */)
18366 {
18367     regMaskTP availableSet = gtRsvdRegs & mask;
18368     assert(genCountBits(availableSet) == 1);
18369     regNumber tempReg = genRegNumFromMask(availableSet);
18370     INDEBUG(gtRsvdRegs &= ~availableSet;) // Remove the register from the set, so it can't be used again.
18371     return tempReg;
18372 }
18373
18374 //------------------------------------------------------------------------
18375 // ExtractTempReg: Find the lowest number temporary register from the gtRsvdRegs set
18376 // that is also in the optional given mask (typically, RBM_ALLINT or RBM_ALLFLOAT),
18377 // and return it. Remove this register from the temporary register set, so it won't
18378 // be returned again.
18379 //
18380 // Arguments:
18381 //    mask - (optional) Extract an available temporary register only in this set.
18382 //
18383 // Return Value:
18384 //    Available temporary register in given mask.
18385 //
18386 regNumber GenTree::ExtractTempReg(regMaskTP mask /* = (regMaskTP)-1 */)
18387 {
18388     regMaskTP availableSet = gtRsvdRegs & mask;
18389     assert(genCountBits(availableSet) >= 1);
18390     regMaskTP tempRegMask = genFindLowestBit(availableSet);
18391     gtRsvdRegs &= ~tempRegMask;
18392     return genRegNumFromMask(tempRegMask);
18393 }