Merge pull request #11448 from DrewScoggins/AddPriority
[platform/upstream/coreclr.git] / src / jit / codegenxarch.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                        Amd64/x86 Code Generator                           XX
9 XX                                                                           XX
10 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
11 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
12 */
13 #include "jitpch.h"
14 #ifdef _MSC_VER
15 #pragma hdrstop
16 #endif
17
18 #ifndef LEGACY_BACKEND // This file is ONLY used for the RyuJIT backend that uses the linear scan register allocator.
19
20 #ifdef _TARGET_XARCH_
21 #include "emit.h"
22 #include "codegen.h"
23 #include "lower.h"
24 #include "gcinfo.h"
25 #include "gcinfoencoder.h"
26
27 /*****************************************************************************
28  *
29  *  Generate code that will set the given register to the integer constant.
30  */
31
32 void CodeGen::genSetRegToIcon(regNumber reg, ssize_t val, var_types type, insFlags flags)
33 {
34     // Reg cannot be a FP reg
35     assert(!genIsValidFloatReg(reg));
36
37     // The only TYP_REF constant that can come this path is a managed 'null' since it is not
38     // relocatable.  Other ref type constants (e.g. string objects) go through a different
39     // code path.
40     noway_assert(type != TYP_REF || val == 0);
41
42     if (val == 0)
43     {
44         instGen_Set_Reg_To_Zero(emitActualTypeSize(type), reg, flags);
45     }
46     else
47     {
48         // TODO-XArch-CQ: needs all the optimized cases
49         getEmitter()->emitIns_R_I(INS_mov, emitActualTypeSize(type), reg, val);
50     }
51 }
52
53 /*****************************************************************************
54  *
55  *   Generate code to check that the GS cookie wasn't thrashed by a buffer
56  *   overrun.  If pushReg is true, preserve all registers around code sequence.
57  *   Otherwise ECX could be modified.
58  *
59  *   Implementation Note: pushReg = true, in case of tail calls.
60  */
61 void CodeGen::genEmitGSCookieCheck(bool pushReg)
62 {
63     noway_assert(compiler->gsGlobalSecurityCookieAddr || compiler->gsGlobalSecurityCookieVal);
64
65     // Make sure that EAX is reported as live GC-ref so that any GC that kicks in while
66     // executing GS cookie check will not collect the object pointed to by EAX.
67     //
68     // For Amd64 System V, a two-register-returned struct could be returned in RAX and RDX
69     // In such case make sure that the correct GC-ness of RDX is reported as well, so
70     // a GC object pointed by RDX will not be collected.
71     if (!pushReg)
72     {
73         // Handle multi-reg return type values
74         if (compiler->compMethodReturnsMultiRegRetType())
75         {
76             ReturnTypeDesc retTypeDesc;
77             if (varTypeIsLong(compiler->info.compRetNativeType))
78             {
79                 retTypeDesc.InitializeLongReturnType(compiler);
80             }
81             else // we must have a struct return type
82             {
83                 retTypeDesc.InitializeStructReturnType(compiler, compiler->info.compMethodInfo->args.retTypeClass);
84             }
85
86             unsigned regCount = retTypeDesc.GetReturnRegCount();
87
88             // Only x86 and x64 Unix ABI allows multi-reg return and
89             // number of result regs should be equal to MAX_RET_REG_COUNT.
90             assert(regCount == MAX_RET_REG_COUNT);
91
92             for (unsigned i = 0; i < regCount; ++i)
93             {
94                 gcInfo.gcMarkRegPtrVal(retTypeDesc.GetABIReturnReg(i), retTypeDesc.GetReturnRegType(i));
95             }
96         }
97         else if (compiler->compMethodReturnsRetBufAddr())
98         {
99             // This is for returning in an implicit RetBuf.
100             // If the address of the buffer is returned in REG_INTRET, mark the content of INTRET as ByRef.
101
102             // In case the return is in an implicit RetBuf, the native return type should be a struct
103             assert(varTypeIsStruct(compiler->info.compRetNativeType));
104
105             gcInfo.gcMarkRegPtrVal(REG_INTRET, TYP_BYREF);
106         }
107         // ... all other cases.
108         else
109         {
110 #ifdef _TARGET_AMD64_
111             // For x64, structs that are not returned in registers are always
112             // returned in implicit RetBuf. If we reached here, we should not have
113             // a RetBuf and the return type should not be a struct.
114             assert(compiler->info.compRetBuffArg == BAD_VAR_NUM);
115             assert(!varTypeIsStruct(compiler->info.compRetNativeType));
116 #endif // _TARGET_AMD64_
117
118             // For x86 Windows we can't make such assertions since we generate code for returning of
119             // the RetBuf in REG_INTRET only when the ProfilerHook is enabled. Otherwise
120             // compRetNativeType could be TYP_STRUCT.
121             gcInfo.gcMarkRegPtrVal(REG_INTRET, compiler->info.compRetNativeType);
122         }
123     }
124
125     regNumber regGSCheck;
126     regMaskTP regMaskGSCheck = RBM_NONE;
127
128     if (!pushReg)
129     {
130         // Non-tail call: we can use any callee trash register that is not
131         // a return register or contain 'this' pointer (keep alive this), since
132         // we are generating GS cookie check after a GT_RETURN block.
133         // Note: On Amd64 System V RDX is an arg register - REG_ARG_2 - as well
134         // as return register for two-register-returned structs.
135         if (compiler->lvaKeepAliveAndReportThis() && compiler->lvaTable[compiler->info.compThisArg].lvRegister &&
136             (compiler->lvaTable[compiler->info.compThisArg].lvRegNum == REG_ARG_0))
137         {
138             regGSCheck = REG_ARG_1;
139         }
140         else
141         {
142             regGSCheck = REG_ARG_0;
143         }
144     }
145     else
146     {
147 #ifdef _TARGET_X86_
148         // It doesn't matter which register we pick, since we're going to save and restore it
149         // around the check.
150         // TODO-CQ: Can we optimize the choice of register to avoid doing the push/pop sometimes?
151         regGSCheck     = REG_EAX;
152         regMaskGSCheck = RBM_EAX;
153 #else  // !_TARGET_X86_
154         // Tail calls from methods that need GS check:  We need to preserve registers while
155         // emitting GS cookie check for a tail prefixed call or a jmp. To emit GS cookie
156         // check, we might need a register. This won't be an issue for jmp calls for the
157         // reason mentioned below (see comment starting with "Jmp Calls:").
158         //
159         // The following are the possible solutions in case of tail prefixed calls:
160         // 1) Use R11 - ignore tail prefix on calls that need to pass a param in R11 when
161         //    present in methods that require GS cookie check.  Rest of the tail calls that
162         //    do not require R11 will be honored.
163         // 2) Internal register - GT_CALL node reserves an internal register and emits GS
164         //    cookie check as part of tail call codegen. GenExitCode() needs to special case
165         //    fast tail calls implemented as epilog+jmp or such tail calls should always get
166         //    dispatched via helper.
167         // 3) Materialize GS cookie check as a sperate node hanging off GT_CALL node in
168         //    right execution order during rationalization.
169         //
170         // There are two calls that use R11: VSD and calli pinvokes with cookie param. Tail
171         // prefix on pinvokes is ignored.  That is, options 2 and 3 will allow tail prefixed
172         // VSD calls from methods that need GS check.
173         //
174         // Tail prefixed calls: Right now for Jit64 compat, method requiring GS cookie check
175         // ignores tail prefix.  In future, if we intend to support tail calls from such a method,
176         // consider one of the options mentioned above.  For now adding an assert that we don't
177         // expect to see a tail call in a method that requires GS check.
178         noway_assert(!compiler->compTailCallUsed);
179
180         // Jmp calls: specify method handle using which JIT queries VM for its entry point
181         // address and hence it can neither be a VSD call nor PInvoke calli with cookie
182         // parameter.  Therefore, in case of jmp calls it is safe to use R11.
183         regGSCheck = REG_R11;
184 #endif // !_TARGET_X86_
185     }
186
187     regMaskTP byrefPushedRegs = RBM_NONE;
188     regMaskTP norefPushedRegs = RBM_NONE;
189     regMaskTP pushedRegs      = RBM_NONE;
190
191     if (compiler->gsGlobalSecurityCookieAddr == nullptr)
192     {
193 #if defined(_TARGET_AMD64_)
194         // If GS cookie value fits within 32-bits we can use 'cmp mem64, imm32'.
195         // Otherwise, load the value into a reg and use 'cmp mem64, reg64'.
196         if ((int)compiler->gsGlobalSecurityCookieVal != (ssize_t)compiler->gsGlobalSecurityCookieVal)
197         {
198             genSetRegToIcon(regGSCheck, compiler->gsGlobalSecurityCookieVal, TYP_I_IMPL);
199             getEmitter()->emitIns_S_R(INS_cmp, EA_PTRSIZE, regGSCheck, compiler->lvaGSSecurityCookie, 0);
200         }
201         else
202 #endif // defined(_TARGET_AMD64_)
203         {
204             assert((int)compiler->gsGlobalSecurityCookieVal == (ssize_t)compiler->gsGlobalSecurityCookieVal);
205             getEmitter()->emitIns_S_I(INS_cmp, EA_PTRSIZE, compiler->lvaGSSecurityCookie, 0,
206                                       (int)compiler->gsGlobalSecurityCookieVal);
207         }
208     }
209     else
210     {
211         // Ngen case - GS cookie value needs to be accessed through an indirection.
212
213         pushedRegs = genPushRegs(regMaskGSCheck, &byrefPushedRegs, &norefPushedRegs);
214
215         instGen_Set_Reg_To_Imm(EA_HANDLE_CNS_RELOC, regGSCheck, (ssize_t)compiler->gsGlobalSecurityCookieAddr);
216         getEmitter()->emitIns_R_AR(ins_Load(TYP_I_IMPL), EA_PTRSIZE, regGSCheck, regGSCheck, 0);
217         getEmitter()->emitIns_S_R(INS_cmp, EA_PTRSIZE, regGSCheck, compiler->lvaGSSecurityCookie, 0);
218     }
219
220     BasicBlock*  gsCheckBlk = genCreateTempLabel();
221     emitJumpKind jmpEqual   = genJumpKindForOper(GT_EQ, CK_SIGNED);
222     inst_JMP(jmpEqual, gsCheckBlk);
223     genEmitHelperCall(CORINFO_HELP_FAIL_FAST, 0, EA_UNKNOWN);
224     genDefineTempLabel(gsCheckBlk);
225
226     genPopRegs(pushedRegs, byrefPushedRegs, norefPushedRegs);
227 }
228
229 BasicBlock* CodeGen::genCallFinally(BasicBlock* block)
230 {
231 #if FEATURE_EH_FUNCLETS
232     // Generate a call to the finally, like this:
233     //      mov         rcx,qword ptr [rbp + 20H]       // Load rcx with PSPSym
234     //      call        finally-funclet
235     //      jmp         finally-return                  // Only for non-retless finally calls
236     // The jmp can be a NOP if we're going to the next block.
237     // If we're generating code for the main function (not a funclet), and there is no localloc,
238     // then RSP at this point is the same value as that stored in the PSPSym. So just copy RSP
239     // instead of loading the PSPSym in this case, or if PSPSym is not used (CoreRT ABI).
240
241     if ((compiler->lvaPSPSym == BAD_VAR_NUM) ||
242         (!compiler->compLocallocUsed && (compiler->funCurrentFunc()->funKind == FUNC_ROOT)))
243     {
244 #ifndef UNIX_X86_ABI
245         inst_RV_RV(INS_mov, REG_ARG_0, REG_SPBASE, TYP_I_IMPL);
246 #endif // !UNIX_X86_ABI
247     }
248     else
249     {
250         getEmitter()->emitIns_R_S(ins_Load(TYP_I_IMPL), EA_PTRSIZE, REG_ARG_0, compiler->lvaPSPSym, 0);
251     }
252     getEmitter()->emitIns_J(INS_call, block->bbJumpDest);
253
254     if (block->bbFlags & BBF_RETLESS_CALL)
255     {
256         // We have a retless call, and the last instruction generated was a call.
257         // If the next block is in a different EH region (or is the end of the code
258         // block), then we need to generate a breakpoint here (since it will never
259         // get executed) to get proper unwind behavior.
260
261         if ((block->bbNext == nullptr) || !BasicBlock::sameEHRegion(block, block->bbNext))
262         {
263             instGen(INS_BREAKPOINT); // This should never get executed
264         }
265     }
266     else
267     {
268 // TODO-Linux-x86: Do we need to handle the GC information for this NOP or JMP specially, as is done for other
269 // architectures?
270 #ifndef JIT32_GCENCODER
271         // Because of the way the flowgraph is connected, the liveness info for this one instruction
272         // after the call is not (can not be) correct in cases where a variable has a last use in the
273         // handler.  So turn off GC reporting for this single instruction.
274         getEmitter()->emitDisableGC();
275 #endif // JIT32_GCENCODER
276
277         // Now go to where the finally funclet needs to return to.
278         if (block->bbNext->bbJumpDest == block->bbNext->bbNext)
279         {
280             // Fall-through.
281             // TODO-XArch-CQ: Can we get rid of this instruction, and just have the call return directly
282             // to the next instruction? This would depend on stack walking from within the finally
283             // handler working without this instruction being in this special EH region.
284             instGen(INS_nop);
285         }
286         else
287         {
288             inst_JMP(EJ_jmp, block->bbNext->bbJumpDest);
289         }
290
291 #ifndef JIT32_GCENCODER
292         getEmitter()->emitEnableGC();
293 #endif // JIT32_GCENCODER
294     }
295
296 #else // !FEATURE_EH_FUNCLETS
297
298     // If we are about to invoke a finally locally from a try block, we have to set the ShadowSP slot
299     // corresponding to the finally's nesting level. When invoked in response to an exception, the
300     // EE does this.
301     //
302     // We have a BBJ_CALLFINALLY followed by a BBJ_ALWAYS.
303     //
304     // We will emit :
305     //      mov [ebp - (n + 1)], 0
306     //      mov [ebp -  n     ], 0xFC
307     //      push &step
308     //      jmp  finallyBlock
309     // ...
310     // step:
311     //      mov [ebp -  n     ], 0
312     //      jmp leaveTarget
313     // ...
314     // leaveTarget:
315
316     noway_assert(isFramePointerUsed());
317
318     // Get the nesting level which contains the finally
319     unsigned finallyNesting = 0;
320     compiler->fgGetNestingLevel(block, &finallyNesting);
321
322     // The last slot is reserved for ICodeManager::FixContext(ppEndRegion)
323     unsigned filterEndOffsetSlotOffs;
324     filterEndOffsetSlotOffs = (unsigned)(compiler->lvaLclSize(compiler->lvaShadowSPslotsVar) - TARGET_POINTER_SIZE);
325
326     unsigned curNestingSlotOffs;
327     curNestingSlotOffs = (unsigned)(filterEndOffsetSlotOffs - ((finallyNesting + 1) * TARGET_POINTER_SIZE));
328
329     // Zero out the slot for the next nesting level
330     instGen_Store_Imm_Into_Lcl(TYP_I_IMPL, EA_PTRSIZE, 0, compiler->lvaShadowSPslotsVar,
331                                curNestingSlotOffs - TARGET_POINTER_SIZE);
332     instGen_Store_Imm_Into_Lcl(TYP_I_IMPL, EA_PTRSIZE, LCL_FINALLY_MARK, compiler->lvaShadowSPslotsVar,
333                                curNestingSlotOffs);
334
335     // Now push the address where the finally funclet should return to directly.
336     if (!(block->bbFlags & BBF_RETLESS_CALL))
337     {
338         assert(block->isBBCallAlwaysPair());
339         getEmitter()->emitIns_J(INS_push_hide, block->bbNext->bbJumpDest);
340     }
341     else
342     {
343         // EE expects a DWORD, so we give him 0
344         inst_IV(INS_push_hide, 0);
345     }
346
347     // Jump to the finally BB
348     inst_JMP(EJ_jmp, block->bbJumpDest);
349
350 #endif // !FEATURE_EH_FUNCLETS
351
352     // The BBJ_ALWAYS is used because the BBJ_CALLFINALLY can't point to the
353     // jump target using bbJumpDest - that is already used to point
354     // to the finally block. So just skip past the BBJ_ALWAYS unless the
355     // block is RETLESS.
356     if (!(block->bbFlags & BBF_RETLESS_CALL))
357     {
358         assert(block->isBBCallAlwaysPair());
359         block = block->bbNext;
360     }
361     return block;
362 }
363
364 #if FEATURE_EH_FUNCLETS
365 void CodeGen::genEHCatchRet(BasicBlock* block)
366 {
367     // Set RAX to the address the VM should return to after the catch.
368     // Generate a RIP-relative
369     //         lea reg, [rip + disp32] ; the RIP is implicit
370     // which will be position-indepenent.
371     getEmitter()->emitIns_R_L(INS_lea, EA_PTR_DSP_RELOC, block->bbJumpDest, REG_INTRET);
372 }
373
374 #else // !FEATURE_EH_FUNCLETS
375
376 void CodeGen::genEHFinallyOrFilterRet(BasicBlock* block)
377 {
378     // The last statement of the block must be a GT_RETFILT, which has already been generated.
379     assert(block->lastNode() != nullptr);
380     assert(block->lastNode()->OperGet() == GT_RETFILT);
381
382     if (block->bbJumpKind == BBJ_EHFINALLYRET)
383     {
384         assert(block->lastNode()->gtOp.gtOp1 == nullptr); // op1 == nullptr means endfinally
385
386         // Return using a pop-jmp sequence. As the "try" block calls
387         // the finally with a jmp, this leaves the x86 call-ret stack
388         // balanced in the normal flow of path.
389
390         noway_assert(isFramePointerRequired());
391         inst_RV(INS_pop_hide, REG_EAX, TYP_I_IMPL);
392         inst_RV(INS_i_jmp, REG_EAX, TYP_I_IMPL);
393     }
394     else
395     {
396         assert(block->bbJumpKind == BBJ_EHFILTERRET);
397
398         // The return value has already been computed.
399         instGen_Return(0);
400     }
401 }
402
403 #endif // !FEATURE_EH_FUNCLETS
404
405 //  Move an immediate value into an integer register
406
407 void CodeGen::instGen_Set_Reg_To_Imm(emitAttr size, regNumber reg, ssize_t imm, insFlags flags)
408 {
409     // reg cannot be a FP register
410     assert(!genIsValidFloatReg(reg));
411
412     if (!compiler->opts.compReloc)
413     {
414         size = EA_SIZE(size); // Strip any Reloc flags from size if we aren't doing relocs
415     }
416
417     if ((imm == 0) && !EA_IS_RELOC(size))
418     {
419         instGen_Set_Reg_To_Zero(size, reg, flags);
420     }
421     else
422     {
423         if (genDataIndirAddrCanBeEncodedAsPCRelOffset(imm))
424         {
425             getEmitter()->emitIns_R_AI(INS_lea, EA_PTR_DSP_RELOC, reg, imm);
426         }
427         else
428         {
429             getEmitter()->emitIns_R_I(INS_mov, size, reg, imm);
430         }
431     }
432     regTracker.rsTrackRegIntCns(reg, imm);
433 }
434
435 /***********************************************************************************
436  *
437  * Generate code to set a register 'targetReg' of type 'targetType' to the constant
438  * specified by the constant (GT_CNS_INT or GT_CNS_DBL) in 'tree'. This does not call
439  * genProduceReg() on the target register.
440  */
441 void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, GenTreePtr tree)
442 {
443
444     switch (tree->gtOper)
445     {
446         case GT_CNS_INT:
447         {
448             // relocatable values tend to come down as a CNS_INT of native int type
449             // so the line between these two opcodes is kind of blurry
450             GenTreeIntConCommon* con    = tree->AsIntConCommon();
451             ssize_t              cnsVal = con->IconValue();
452
453             if (con->ImmedValNeedsReloc(compiler))
454             {
455                 instGen_Set_Reg_To_Imm(EA_HANDLE_CNS_RELOC, targetReg, cnsVal);
456                 regTracker.rsTrackRegTrash(targetReg);
457             }
458             else
459             {
460                 genSetRegToIcon(targetReg, cnsVal, targetType);
461             }
462         }
463         break;
464
465         case GT_CNS_DBL:
466         {
467             double constValue = tree->gtDblCon.gtDconVal;
468
469             // Make sure we use "xorpd reg, reg"  only for +ve zero constant (0.0) and not for -ve zero (-0.0)
470             if (*(__int64*)&constValue == 0)
471             {
472                 // A faster/smaller way to generate 0
473                 instruction ins = genGetInsForOper(GT_XOR, targetType);
474                 inst_RV_RV(ins, targetReg, targetReg, targetType);
475             }
476             else
477             {
478                 GenTreePtr cns;
479                 if (targetType == TYP_FLOAT)
480                 {
481                     float f = forceCastToFloat(constValue);
482                     cns     = genMakeConst(&f, targetType, tree, false);
483                 }
484                 else
485                 {
486                     cns = genMakeConst(&constValue, targetType, tree, true);
487                 }
488
489                 inst_RV_TT(ins_Load(targetType), targetReg, cns);
490             }
491         }
492         break;
493
494         default:
495             unreached();
496     }
497 }
498
499 // Generate code to get the high N bits of a N*N=2N bit multiplication result
500 void CodeGen::genCodeForMulHi(GenTreeOp* treeNode)
501 {
502     if (treeNode->OperGet() == GT_MULHI)
503     {
504         assert(!(treeNode->gtFlags & GTF_UNSIGNED));
505     }
506     assert(!treeNode->gtOverflowEx());
507
508     regNumber targetReg  = treeNode->gtRegNum;
509     var_types targetType = treeNode->TypeGet();
510     emitter*  emit       = getEmitter();
511     emitAttr  size       = emitTypeSize(treeNode);
512     GenTree*  op1        = treeNode->gtOp.gtOp1;
513     GenTree*  op2        = treeNode->gtOp.gtOp2;
514
515     // to get the high bits of the multiply, we are constrained to using the
516     // 1-op form:  RDX:RAX = RAX * rm
517     // The 3-op form (Rx=Ry*Rz) does not support it.
518
519     genConsumeOperands(treeNode->AsOp());
520
521     GenTree* regOp = op1;
522     GenTree* rmOp  = op2;
523
524     // Set rmOp to the memory operand (if any)
525     if (op1->isUsedFromMemory() || (op2->isUsedFromReg() && (op2->gtRegNum == REG_RAX)))
526     {
527         regOp = op2;
528         rmOp  = op1;
529     }
530     assert(regOp->isUsedFromReg());
531
532     // Setup targetReg when neither of the source operands was a matching register
533     if (regOp->gtRegNum != REG_RAX)
534     {
535         inst_RV_RV(ins_Copy(targetType), REG_RAX, regOp->gtRegNum, targetType);
536     }
537
538     instruction ins;
539     if ((treeNode->gtFlags & GTF_UNSIGNED) == 0)
540     {
541         ins = INS_imulEAX;
542     }
543     else
544     {
545         ins = INS_mulEAX;
546     }
547     emit->emitInsBinary(ins, size, treeNode, rmOp);
548
549     // Move the result to the desired register, if necessary
550     if (treeNode->OperGet() == GT_MULHI && targetReg != REG_RDX)
551     {
552         inst_RV_RV(INS_mov, targetReg, REG_RDX, targetType);
553     }
554 }
555
556 #ifdef _TARGET_X86_
557 //------------------------------------------------------------------------
558 // genCodeForLongUMod: Generate code for a tree of the form
559 //                     `(umod (gt_long x y) (const int))`
560 //
561 // Arguments:
562 //   node - the node for which to generate code
563 //
564 void CodeGen::genCodeForLongUMod(GenTreeOp* node)
565 {
566     assert(node != nullptr);
567     assert(node->OperGet() == GT_UMOD);
568     assert(node->TypeGet() == TYP_INT);
569
570     GenTreeOp* const dividend = node->gtOp1->AsOp();
571     assert(dividend->OperGet() == GT_LONG);
572     assert(varTypeIsLong(dividend));
573
574     genConsumeOperands(node);
575
576     GenTree* const dividendLo = dividend->gtOp1;
577     GenTree* const dividendHi = dividend->gtOp2;
578     assert(dividendLo->isUsedFromReg());
579     assert(dividendHi->isUsedFromReg());
580
581     GenTree* const divisor = node->gtOp2;
582     assert(divisor->gtSkipReloadOrCopy()->OperGet() == GT_CNS_INT);
583     assert(divisor->gtSkipReloadOrCopy()->isUsedFromReg());
584     assert(divisor->gtSkipReloadOrCopy()->AsIntCon()->gtIconVal >= 2);
585     assert(divisor->gtSkipReloadOrCopy()->AsIntCon()->gtIconVal <= 0x3fffffff);
586
587     // dividendLo must be in RAX; dividendHi must be in RDX
588     genCopyRegIfNeeded(dividendLo, REG_EAX);
589     genCopyRegIfNeeded(dividendHi, REG_EDX);
590
591     // At this point, EAX:EDX contains the 64bit dividend and op2->gtRegNum
592     // contains the 32bit divisor. We want to generate the following code:
593     //
594     //   cmp edx, divisor->gtRegNum
595     //   jb noOverflow
596     //
597     //   mov temp, eax
598     //   mov eax, edx
599     //   xor edx, edx
600     //   div divisor->gtRegNum
601     //   mov eax, temp
602     //
603     // noOverflow:
604     //   div divisor->gtRegNum
605     //
606     // This works because (a * 2^32 + b) % c = ((a % c) * 2^32 + b) % c.
607
608     BasicBlock* const noOverflow = genCreateTempLabel();
609
610     //   cmp edx, divisor->gtRegNum
611     //   jb noOverflow
612     inst_RV_RV(INS_cmp, REG_EDX, divisor->gtRegNum);
613     inst_JMP(EJ_jb, noOverflow);
614
615     //   mov temp, eax
616     //   mov eax, edx
617     //   xor edx, edx
618     //   div divisor->gtRegNum
619     //   mov eax, temp
620     const regNumber tempReg = node->GetSingleTempReg();
621     inst_RV_RV(INS_mov, tempReg, REG_EAX, TYP_INT);
622     inst_RV_RV(INS_mov, REG_EAX, REG_EDX, TYP_INT);
623     instGen_Set_Reg_To_Zero(EA_PTRSIZE, REG_EDX);
624     inst_RV(INS_div, divisor->gtRegNum, TYP_INT);
625     inst_RV_RV(INS_mov, REG_EAX, tempReg, TYP_INT);
626
627     // noOverflow:
628     //   div divisor->gtRegNum
629     genDefineTempLabel(noOverflow);
630     inst_RV(INS_div, divisor->gtRegNum, TYP_INT);
631
632     const regNumber targetReg = node->gtRegNum;
633     if (targetReg != REG_EDX)
634     {
635         inst_RV_RV(INS_mov, targetReg, REG_RDX, TYP_INT);
636     }
637     genProduceReg(node);
638 }
639 #endif // _TARGET_X86_
640
641 //------------------------------------------------------------------------
642 // genCodeForDivMod: Generate code for a DIV or MOD operation.
643 //
644 // Arguments:
645 //    treeNode - the node to generate the code for
646 //
647 void CodeGen::genCodeForDivMod(GenTreeOp* treeNode)
648 {
649     GenTree* dividend = treeNode->gtOp1;
650 #ifdef _TARGET_X86_
651     if (varTypeIsLong(dividend->TypeGet()))
652     {
653         genCodeForLongUMod(treeNode);
654         return;
655     }
656 #endif // _TARGET_X86_
657
658     GenTree*   divisor    = treeNode->gtOp2;
659     genTreeOps oper       = treeNode->OperGet();
660     emitAttr   size       = emitTypeSize(treeNode);
661     regNumber  targetReg  = treeNode->gtRegNum;
662     var_types  targetType = treeNode->TypeGet();
663     emitter*   emit       = getEmitter();
664
665     // dividend is in a register.
666     assert(dividend->isUsedFromReg());
667
668     genConsumeOperands(treeNode->AsOp());
669     if (varTypeIsFloating(targetType))
670     {
671         // Check that divisor is a valid operand.
672         // Note that a reg optional operand is a treated as a memory op
673         // if no register is allocated to it.
674         assert(divisor->isUsedFromReg() || divisor->isMemoryOp() || divisor->IsCnsFltOrDbl() ||
675                divisor->IsRegOptional());
676
677         // Floating point div/rem operation
678         assert(oper == GT_DIV || oper == GT_MOD);
679
680         if (dividend->gtRegNum == targetReg)
681         {
682             emit->emitInsBinary(genGetInsForOper(treeNode->gtOper, targetType), size, treeNode, divisor);
683         }
684         else if (divisor->isUsedFromReg() && divisor->gtRegNum == targetReg)
685         {
686             // It is not possible to generate 2-operand divss or divsd where reg2 = reg1 / reg2
687             // because divss/divsd reg1, reg2 will over-write reg1.  Therefore, in case of AMD64
688             // LSRA has to make sure that such a register assignment is not generated for floating
689             // point div/rem operations.
690             noway_assert(
691                 !"GT_DIV/GT_MOD (float): case of reg2 = reg1 / reg2, LSRA should never generate such a reg assignment");
692         }
693         else
694         {
695             inst_RV_RV(ins_Copy(targetType), targetReg, dividend->gtRegNum, targetType);
696             emit->emitInsBinary(genGetInsForOper(treeNode->gtOper, targetType), size, treeNode, divisor);
697         }
698     }
699     else
700     {
701         // dividend must be in RAX
702         genCopyRegIfNeeded(dividend, REG_RAX);
703
704         // zero or sign extend rax to rdx
705         if (oper == GT_UMOD || oper == GT_UDIV)
706         {
707             instGen_Set_Reg_To_Zero(EA_PTRSIZE, REG_EDX);
708         }
709         else
710         {
711             emit->emitIns(INS_cdq, size);
712             // the cdq instruction writes RDX, So clear the gcInfo for RDX
713             gcInfo.gcMarkRegSetNpt(RBM_RDX);
714         }
715
716         // Perform the 'targetType' (64-bit or 32-bit) divide instruction
717         instruction ins;
718         if (oper == GT_UMOD || oper == GT_UDIV)
719         {
720             ins = INS_div;
721         }
722         else
723         {
724             ins = INS_idiv;
725         }
726
727         emit->emitInsBinary(ins, size, treeNode, divisor);
728
729         // DIV/IDIV instructions always store the quotient in RAX and the remainder in RDX.
730         // Move the result to the desired register, if necessary
731         if (oper == GT_DIV || oper == GT_UDIV)
732         {
733             if (targetReg != REG_RAX)
734             {
735                 inst_RV_RV(INS_mov, targetReg, REG_RAX, targetType);
736             }
737         }
738         else
739         {
740             assert((oper == GT_MOD) || (oper == GT_UMOD));
741             if (targetReg != REG_RDX)
742             {
743                 inst_RV_RV(INS_mov, targetReg, REG_RDX, targetType);
744             }
745         }
746     }
747     genProduceReg(treeNode);
748 }
749
750 //------------------------------------------------------------------------
751 // genCodeForBinary: Generate code for many binary arithmetic operators
752 // This method is expected to have called genConsumeOperands() before calling it.
753 //
754 // Arguments:
755 //    treeNode - The binary operation for which we are generating code.
756 //
757 // Return Value:
758 //    None.
759 //
760 // Notes:
761 //    Mul and div variants have special constraints on x64 so are not handled here.
762 //    See teh assert below for the operators that are handled.
763
764 void CodeGen::genCodeForBinary(GenTree* treeNode)
765 {
766     const genTreeOps oper       = treeNode->OperGet();
767     regNumber        targetReg  = treeNode->gtRegNum;
768     var_types        targetType = treeNode->TypeGet();
769     emitter*         emit       = getEmitter();
770
771 #if defined(_TARGET_64BIT_)
772     assert(oper == GT_OR || oper == GT_XOR || oper == GT_AND || oper == GT_ADD || oper == GT_SUB);
773 #else  // !defined(_TARGET_64BIT_)
774     assert(oper == GT_OR || oper == GT_XOR || oper == GT_AND || oper == GT_ADD_LO || oper == GT_ADD_HI ||
775            oper == GT_SUB_LO || oper == GT_SUB_HI || oper == GT_MUL_LONG || oper == GT_DIV_HI || oper == GT_MOD_HI ||
776            oper == GT_ADD || oper == GT_SUB);
777 #endif // !defined(_TARGET_64BIT_)
778
779     GenTreePtr op1 = treeNode->gtGetOp1();
780     GenTreePtr op2 = treeNode->gtGetOp2();
781
782     // Commutative operations can mark op1 as contained or reg-optional to generate "op reg, memop/immed"
783     if (!op1->isUsedFromReg())
784     {
785         assert(treeNode->OperIsCommutative());
786         assert(op1->isMemoryOp() || op1->IsCnsNonZeroFltOrDbl() || op1->IsIntCnsFitsInI32() || op1->IsRegOptional());
787
788         op1 = treeNode->gtGetOp2();
789         op2 = treeNode->gtGetOp1();
790     }
791
792     instruction ins = genGetInsForOper(treeNode->OperGet(), targetType);
793
794     // The arithmetic node must be sitting in a register (since it's not contained)
795     noway_assert(targetReg != REG_NA);
796
797     regNumber op1reg = op1->isUsedFromReg() ? op1->gtRegNum : REG_NA;
798     regNumber op2reg = op2->isUsedFromReg() ? op2->gtRegNum : REG_NA;
799
800     GenTreePtr dst;
801     GenTreePtr src;
802
803     // This is the case of reg1 = reg1 op reg2
804     // We're ready to emit the instruction without any moves
805     if (op1reg == targetReg)
806     {
807         dst = op1;
808         src = op2;
809     }
810     // We have reg1 = reg2 op reg1
811     // In order for this operation to be correct
812     // we need that op is a commutative operation so
813     // we can convert it into reg1 = reg1 op reg2 and emit
814     // the same code as above
815     else if (op2reg == targetReg)
816     {
817         noway_assert(GenTree::OperIsCommutative(oper));
818         dst = op2;
819         src = op1;
820     }
821     // now we know there are 3 different operands so attempt to use LEA
822     else if (oper == GT_ADD && !varTypeIsFloating(treeNode) && !treeNode->gtOverflowEx() // LEA does not set flags
823              && (op2->isContainedIntOrIImmed() || op2->isUsedFromReg()) && !treeNode->gtSetFlags())
824     {
825         if (op2->isContainedIntOrIImmed())
826         {
827             emit->emitIns_R_AR(INS_lea, emitTypeSize(treeNode), targetReg, op1reg,
828                                (int)op2->AsIntConCommon()->IconValue());
829         }
830         else
831         {
832             assert(op2reg != REG_NA);
833             emit->emitIns_R_ARX(INS_lea, emitTypeSize(treeNode), targetReg, op1reg, op2reg, 1, 0);
834         }
835         genProduceReg(treeNode);
836         return;
837     }
838     // dest, op1 and op2 registers are different:
839     // reg3 = reg1 op reg2
840     // We can implement this by issuing a mov:
841     // reg3 = reg1
842     // reg3 = reg3 op reg2
843     else
844     {
845         inst_RV_RV(ins_Copy(targetType), targetReg, op1reg, targetType);
846         regTracker.rsTrackRegCopy(targetReg, op1reg);
847         gcInfo.gcMarkRegPtrVal(targetReg, targetType);
848         dst = treeNode;
849         src = op2;
850     }
851
852     // try to use an inc or dec
853     if (oper == GT_ADD && !varTypeIsFloating(treeNode) && src->isContainedIntOrIImmed() && !treeNode->gtOverflowEx())
854     {
855         if (src->IsIntegralConst(1))
856         {
857             emit->emitIns_R(INS_inc, emitTypeSize(treeNode), targetReg);
858             genProduceReg(treeNode);
859             return;
860         }
861         else if (src->IsIntegralConst(-1))
862         {
863             emit->emitIns_R(INS_dec, emitTypeSize(treeNode), targetReg);
864             genProduceReg(treeNode);
865             return;
866         }
867     }
868     regNumber r = emit->emitInsBinary(ins, emitTypeSize(treeNode), dst, src);
869     noway_assert(r == targetReg);
870
871     if (treeNode->gtOverflowEx())
872     {
873 #if !defined(_TARGET_64BIT_)
874         assert(oper == GT_ADD || oper == GT_SUB || oper == GT_ADD_HI || oper == GT_SUB_HI);
875 #else
876         assert(oper == GT_ADD || oper == GT_SUB);
877 #endif
878         genCheckOverflow(treeNode);
879     }
880     genProduceReg(treeNode);
881 }
882
883 //------------------------------------------------------------------------
884 // isStructReturn: Returns whether the 'treeNode' is returning a struct.
885 //
886 // Arguments:
887 //    treeNode - The tree node to evaluate whether is a struct return.
888 //
889 // Return Value:
890 //    For AMD64 *nix: returns true if the 'treeNode" is a GT_RETURN node, of type struct.
891 //                    Otherwise returns false.
892 //    For other platforms always returns false.
893 //
894 bool CodeGen::isStructReturn(GenTreePtr treeNode)
895 {
896     // This method could be called for 'treeNode' of GT_RET_FILT or GT_RETURN.
897     // For the GT_RET_FILT, the return is always
898     // a bool or a void, for the end of a finally block.
899     noway_assert(treeNode->OperGet() == GT_RETURN || treeNode->OperGet() == GT_RETFILT);
900     if (treeNode->OperGet() != GT_RETURN)
901     {
902         return false;
903     }
904
905 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
906     return varTypeIsStruct(treeNode);
907 #else  // !FEATURE_UNIX_AMD64_STRUCT_PASSING
908     assert(!varTypeIsStruct(treeNode));
909     return false;
910 #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
911 }
912
913 //------------------------------------------------------------------------
914 // genStructReturn: Generates code for returning a struct.
915 //
916 // Arguments:
917 //    treeNode - The GT_RETURN tree node.
918 //
919 // Return Value:
920 //    None
921 //
922 // Assumption:
923 //    op1 of GT_RETURN node is either GT_LCL_VAR or multi-reg GT_CALL
924 void CodeGen::genStructReturn(GenTreePtr treeNode)
925 {
926     assert(treeNode->OperGet() == GT_RETURN);
927     GenTreePtr op1 = treeNode->gtGetOp1();
928
929 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
930     if (op1->OperGet() == GT_LCL_VAR)
931     {
932         GenTreeLclVarCommon* lclVar = op1->AsLclVarCommon();
933         LclVarDsc*           varDsc = &(compiler->lvaTable[lclVar->gtLclNum]);
934         assert(varDsc->lvIsMultiRegRet);
935
936         ReturnTypeDesc retTypeDesc;
937         retTypeDesc.InitializeStructReturnType(compiler, varDsc->lvVerTypeInfo.GetClassHandle());
938         unsigned regCount = retTypeDesc.GetReturnRegCount();
939         assert(regCount == MAX_RET_REG_COUNT);
940
941         if (varTypeIsEnregisterableStruct(op1))
942         {
943             // Right now the only enregistrable structs supported are SIMD vector types.
944             assert(varTypeIsSIMD(op1));
945             assert(op1->isUsedFromReg());
946
947             // This is a case of operand is in a single reg and needs to be
948             // returned in multiple ABI return registers.
949             regNumber opReg = genConsumeReg(op1);
950             regNumber reg0  = retTypeDesc.GetABIReturnReg(0);
951             regNumber reg1  = retTypeDesc.GetABIReturnReg(1);
952
953             if (opReg != reg0 && opReg != reg1)
954             {
955                 // Operand reg is different from return regs.
956                 // Copy opReg to reg0 and let it to be handled by one of the
957                 // two cases below.
958                 inst_RV_RV(ins_Copy(TYP_DOUBLE), reg0, opReg, TYP_DOUBLE);
959                 opReg = reg0;
960             }
961
962             if (opReg == reg0)
963             {
964                 assert(opReg != reg1);
965
966                 // reg0 - already has required 8-byte in bit position [63:0].
967                 // reg1 = opReg.
968                 // swap upper and lower 8-bytes of reg1 so that desired 8-byte is in bit position [63:0].
969                 inst_RV_RV(ins_Copy(TYP_DOUBLE), reg1, opReg, TYP_DOUBLE);
970             }
971             else
972             {
973                 assert(opReg == reg1);
974
975                 // reg0 = opReg.
976                 // swap upper and lower 8-bytes of reg1 so that desired 8-byte is in bit position [63:0].
977                 inst_RV_RV(ins_Copy(TYP_DOUBLE), reg0, opReg, TYP_DOUBLE);
978             }
979             inst_RV_RV_IV(INS_shufpd, EA_16BYTE, reg1, reg1, 0x01);
980         }
981         else
982         {
983             assert(op1->isUsedFromMemory());
984
985             // Copy var on stack into ABI return registers
986             int offset = 0;
987             for (unsigned i = 0; i < regCount; ++i)
988             {
989                 var_types type = retTypeDesc.GetReturnRegType(i);
990                 regNumber reg  = retTypeDesc.GetABIReturnReg(i);
991                 getEmitter()->emitIns_R_S(ins_Load(type), emitTypeSize(type), reg, lclVar->gtLclNum, offset);
992                 offset += genTypeSize(type);
993             }
994         }
995     }
996     else
997     {
998         assert(op1->IsMultiRegCall() || op1->IsCopyOrReloadOfMultiRegCall());
999
1000         genConsumeRegs(op1);
1001
1002         GenTree*        actualOp1   = op1->gtSkipReloadOrCopy();
1003         GenTreeCall*    call        = actualOp1->AsCall();
1004         ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc();
1005         unsigned        regCount    = retTypeDesc->GetReturnRegCount();
1006         assert(regCount == MAX_RET_REG_COUNT);
1007
1008         // Handle circular dependency between call allocated regs and ABI return regs.
1009         //
1010         // It is possible under LSRA stress that originally allocated regs of call node,
1011         // say rax and rdx, are spilled and reloaded to rdx and rax respectively.  But
1012         // GT_RETURN needs to  move values as follows: rdx->rax, rax->rdx. Similar kind
1013         // kind of circular dependency could arise between xmm0 and xmm1 return regs.
1014         // Codegen is expected to handle such circular dependency.
1015         //
1016         var_types regType0      = retTypeDesc->GetReturnRegType(0);
1017         regNumber returnReg0    = retTypeDesc->GetABIReturnReg(0);
1018         regNumber allocatedReg0 = call->GetRegNumByIdx(0);
1019
1020         var_types regType1      = retTypeDesc->GetReturnRegType(1);
1021         regNumber returnReg1    = retTypeDesc->GetABIReturnReg(1);
1022         regNumber allocatedReg1 = call->GetRegNumByIdx(1);
1023
1024         if (op1->IsCopyOrReload())
1025         {
1026             // GT_COPY/GT_RELOAD will have valid reg for those positions
1027             // that need to be copied or reloaded.
1028             regNumber reloadReg = op1->AsCopyOrReload()->GetRegNumByIdx(0);
1029             if (reloadReg != REG_NA)
1030             {
1031                 allocatedReg0 = reloadReg;
1032             }
1033
1034             reloadReg = op1->AsCopyOrReload()->GetRegNumByIdx(1);
1035             if (reloadReg != REG_NA)
1036             {
1037                 allocatedReg1 = reloadReg;
1038             }
1039         }
1040
1041         if (allocatedReg0 == returnReg1 && allocatedReg1 == returnReg0)
1042         {
1043             // Circular dependency - swap allocatedReg0 and allocatedReg1
1044             if (varTypeIsFloating(regType0))
1045             {
1046                 assert(varTypeIsFloating(regType1));
1047
1048                 // The fastest way to swap two XMM regs is using PXOR
1049                 inst_RV_RV(INS_pxor, allocatedReg0, allocatedReg1, TYP_DOUBLE);
1050                 inst_RV_RV(INS_pxor, allocatedReg1, allocatedReg0, TYP_DOUBLE);
1051                 inst_RV_RV(INS_pxor, allocatedReg0, allocatedReg1, TYP_DOUBLE);
1052             }
1053             else
1054             {
1055                 assert(varTypeIsIntegral(regType0));
1056                 assert(varTypeIsIntegral(regType1));
1057                 inst_RV_RV(INS_xchg, allocatedReg1, allocatedReg0, TYP_I_IMPL);
1058             }
1059         }
1060         else if (allocatedReg1 == returnReg0)
1061         {
1062             // Change the order of moves to correctly handle dependency.
1063             if (allocatedReg1 != returnReg1)
1064             {
1065                 inst_RV_RV(ins_Copy(regType1), returnReg1, allocatedReg1, regType1);
1066             }
1067
1068             if (allocatedReg0 != returnReg0)
1069             {
1070                 inst_RV_RV(ins_Copy(regType0), returnReg0, allocatedReg0, regType0);
1071             }
1072         }
1073         else
1074         {
1075             // No circular dependency case.
1076             if (allocatedReg0 != returnReg0)
1077             {
1078                 inst_RV_RV(ins_Copy(regType0), returnReg0, allocatedReg0, regType0);
1079             }
1080
1081             if (allocatedReg1 != returnReg1)
1082             {
1083                 inst_RV_RV(ins_Copy(regType1), returnReg1, allocatedReg1, regType1);
1084             }
1085         }
1086     }
1087 #else
1088     unreached();
1089 #endif
1090 }
1091
1092 //------------------------------------------------------------------------
1093 // genReturn: Generates code for return statement.
1094 //            In case of struct return, delegates to the genStructReturn method.
1095 //
1096 // Arguments:
1097 //    treeNode - The GT_RETURN or GT_RETFILT tree node.
1098 //
1099 // Return Value:
1100 //    None
1101 //
1102 void CodeGen::genReturn(GenTreePtr treeNode)
1103 {
1104     assert(treeNode->OperGet() == GT_RETURN || treeNode->OperGet() == GT_RETFILT);
1105     GenTreePtr op1        = treeNode->gtGetOp1();
1106     var_types  targetType = treeNode->TypeGet();
1107
1108 #ifdef DEBUG
1109     if (targetType == TYP_VOID)
1110     {
1111         assert(op1 == nullptr);
1112     }
1113 #endif
1114
1115 #ifdef _TARGET_X86_
1116     if (treeNode->TypeGet() == TYP_LONG)
1117     {
1118         assert(op1 != nullptr);
1119         noway_assert(op1->OperGet() == GT_LONG);
1120         GenTree* loRetVal = op1->gtGetOp1();
1121         GenTree* hiRetVal = op1->gtGetOp2();
1122         noway_assert((loRetVal->gtRegNum != REG_NA) && (hiRetVal->gtRegNum != REG_NA));
1123
1124         genConsumeReg(loRetVal);
1125         genConsumeReg(hiRetVal);
1126         if (loRetVal->gtRegNum != REG_LNGRET_LO)
1127         {
1128             inst_RV_RV(ins_Copy(targetType), REG_LNGRET_LO, loRetVal->gtRegNum, TYP_INT);
1129         }
1130         if (hiRetVal->gtRegNum != REG_LNGRET_HI)
1131         {
1132             inst_RV_RV(ins_Copy(targetType), REG_LNGRET_HI, hiRetVal->gtRegNum, TYP_INT);
1133         }
1134     }
1135     else
1136 #endif // !defined(_TARGET_X86_)
1137     {
1138         if (isStructReturn(treeNode))
1139         {
1140             genStructReturn(treeNode);
1141         }
1142         else if (targetType != TYP_VOID)
1143         {
1144             assert(op1 != nullptr);
1145             noway_assert(op1->gtRegNum != REG_NA);
1146
1147             // !! NOTE !! genConsumeReg will clear op1 as GC ref after it has
1148             // consumed a reg for the operand. This is because the variable
1149             // is dead after return. But we are issuing more instructions
1150             // like "profiler leave callback" after this consumption. So
1151             // if you are issuing more instructions after this point,
1152             // remember to keep the variable live up until the new method
1153             // exit point where it is actually dead.
1154             genConsumeReg(op1);
1155
1156             regNumber retReg = varTypeIsFloating(treeNode) ? REG_FLOATRET : REG_INTRET;
1157 #ifdef _TARGET_X86_
1158             if (varTypeIsFloating(treeNode))
1159             {
1160                 // Spill the return value register from an XMM register to the stack, then load it on the x87 stack.
1161                 // If it already has a home location, use that. Otherwise, we need a temp.
1162                 if (genIsRegCandidateLocal(op1) && compiler->lvaTable[op1->gtLclVarCommon.gtLclNum].lvOnFrame)
1163                 {
1164                     // Store local variable to its home location, if necessary.
1165                     if ((op1->gtFlags & GTF_REG_VAL) != 0)
1166                     {
1167                         op1->gtFlags &= ~GTF_REG_VAL;
1168                         inst_TT_RV(ins_Store(op1->gtType,
1169                                              compiler->isSIMDTypeLocalAligned(op1->gtLclVarCommon.gtLclNum)),
1170                                    op1, op1->gtRegNum);
1171                     }
1172                     // Now, load it to the fp stack.
1173                     getEmitter()->emitIns_S(INS_fld, emitTypeSize(op1), op1->AsLclVarCommon()->gtLclNum, 0);
1174                 }
1175                 else
1176                 {
1177                     // Spill the value, which should be in a register, then load it to the fp stack.
1178                     // TODO-X86-CQ: Deal with things that are already in memory (don't call genConsumeReg yet).
1179                     op1->gtFlags |= GTF_SPILL;
1180                     regSet.rsSpillTree(op1->gtRegNum, op1);
1181                     op1->gtFlags |= GTF_SPILLED;
1182                     op1->gtFlags &= ~GTF_SPILL;
1183
1184                     TempDsc* t = regSet.rsUnspillInPlace(op1, op1->gtRegNum);
1185                     inst_FS_ST(INS_fld, emitActualTypeSize(op1->gtType), t, 0);
1186                     op1->gtFlags &= ~GTF_SPILLED;
1187                     compiler->tmpRlsTemp(t);
1188                 }
1189             }
1190             else
1191 #endif // _TARGET_X86_
1192             {
1193                 if (op1->gtRegNum != retReg)
1194                 {
1195                     inst_RV_RV(ins_Copy(targetType), retReg, op1->gtRegNum, targetType);
1196                 }
1197             }
1198         }
1199     }
1200
1201 #ifdef PROFILING_SUPPORTED
1202     // !! Note !!
1203     // TODO-AMD64-Unix: If the profiler hook is implemented on *nix, make sure for 2 register returned structs
1204     //                  the RAX and RDX needs to be kept alive. Make the necessary changes in lowerxarch.cpp
1205     //                  in the handling of the GT_RETURN statement.
1206     //                  Such structs containing GC pointers need to be handled by calling gcInfo.gcMarkRegSetNpt
1207     //                  for the return registers containing GC refs.
1208
1209     // There will be a single return block while generating profiler ELT callbacks.
1210     //
1211     // Reason for not materializing Leave callback as a GT_PROF_HOOK node after GT_RETURN:
1212     // In flowgraph and other places assert that the last node of a block marked as
1213     // BBJ_RETURN is either a GT_RETURN or GT_JMP or a tail call.  It would be nice to
1214     // maintain such an invariant irrespective of whether profiler hook needed or not.
1215     // Also, there is not much to be gained by materializing it as an explicit node.
1216     if (compiler->compCurBB == compiler->genReturnBB)
1217     {
1218         // !! NOTE !!
1219         // Since we are invalidating the assumption that we would slip into the epilog
1220         // right after the "return", we need to preserve the return reg's GC state
1221         // across the call until actual method return.
1222         if (varTypeIsGC(compiler->info.compRetType))
1223         {
1224             gcInfo.gcMarkRegPtrVal(REG_INTRET, compiler->info.compRetType);
1225         }
1226
1227         genProfilingLeaveCallback();
1228
1229         if (varTypeIsGC(compiler->info.compRetType))
1230         {
1231             gcInfo.gcMarkRegSetNpt(REG_INTRET);
1232         }
1233     }
1234 #endif
1235 }
1236
1237 //------------------------------------------------------------------------
1238 // genCodeForJumpTrue: Generates code for jmpTrue statement.
1239 //
1240 // Arguments:
1241 //    tree - The GT_JTRUE tree node.
1242 //
1243 // Return Value:
1244 //    None
1245 //
1246 void CodeGen::genCodeForJumpTrue(GenTreePtr tree)
1247 {
1248     GenTree* cmp = tree->gtOp.gtOp1;
1249
1250     assert(cmp->OperIsCompare());
1251     assert(compiler->compCurBB->bbJumpKind == BBJ_COND);
1252
1253 #if !defined(_TARGET_64BIT_)
1254     // Long-typed compares should have been handled by Lowering::LowerCompare.
1255     assert(!varTypeIsLong(cmp->gtGetOp1()));
1256 #endif
1257
1258     // Get the "kind" and type of the comparison.  Note that whether it is an unsigned cmp
1259     // is governed by a flag NOT by the inherent type of the node
1260     // TODO-XArch-CQ: Check if we can use the currently set flags.
1261     emitJumpKind jumpKind[2];
1262     bool         branchToTrueLabel[2];
1263     genJumpKindsForTree(cmp, jumpKind, branchToTrueLabel);
1264
1265     BasicBlock* skipLabel = nullptr;
1266     if (jumpKind[0] != EJ_NONE)
1267     {
1268         BasicBlock* jmpTarget;
1269         if (branchToTrueLabel[0])
1270         {
1271             jmpTarget = compiler->compCurBB->bbJumpDest;
1272         }
1273         else
1274         {
1275             // This case arises only for ordered GT_EQ right now
1276             assert((cmp->gtOper == GT_EQ) && ((cmp->gtFlags & GTF_RELOP_NAN_UN) == 0));
1277             skipLabel = genCreateTempLabel();
1278             jmpTarget = skipLabel;
1279         }
1280
1281         inst_JMP(jumpKind[0], jmpTarget);
1282     }
1283
1284     if (jumpKind[1] != EJ_NONE)
1285     {
1286         // the second conditional branch always has to be to the true label
1287         assert(branchToTrueLabel[1]);
1288         inst_JMP(jumpKind[1], compiler->compCurBB->bbJumpDest);
1289     }
1290
1291     if (skipLabel != nullptr)
1292     {
1293         genDefineTempLabel(skipLabel);
1294     }
1295 }
1296
1297 /*****************************************************************************
1298  *
1299  * Generate code for a single node in the tree.
1300  * Preconditions: All operands have been evaluated
1301  *
1302  */
1303 void CodeGen::genCodeForTreeNode(GenTreePtr treeNode)
1304 {
1305     regNumber targetReg;
1306 #if !defined(_TARGET_64BIT_)
1307     if (treeNode->TypeGet() == TYP_LONG)
1308     {
1309         // All long enregistered nodes will have been decomposed into their
1310         // constituent lo and hi nodes.
1311         targetReg = REG_NA;
1312     }
1313     else
1314 #endif // !defined(_TARGET_64BIT_)
1315     {
1316         targetReg = treeNode->gtRegNum;
1317     }
1318     var_types targetType = treeNode->TypeGet();
1319     emitter*  emit       = getEmitter();
1320
1321 #ifdef DEBUG
1322     // Validate that all the operands for the current node are consumed in order.
1323     // This is important because LSRA ensures that any necessary copies will be
1324     // handled correctly.
1325     lastConsumedNode = nullptr;
1326     if (compiler->verbose)
1327     {
1328         unsigned seqNum = treeNode->gtSeqNum; // Useful for setting a conditional break in Visual Studio
1329         compiler->gtDispLIRNode(treeNode, "Generating: ");
1330     }
1331 #endif // DEBUG
1332
1333     // Is this a node whose value is already in a register?  LSRA denotes this by
1334     // setting the GTF_REUSE_REG_VAL flag.
1335     if (treeNode->IsReuseRegVal())
1336     {
1337         // For now, this is only used for constant nodes.
1338         assert((treeNode->OperIsConst()));
1339         JITDUMP("  TreeNode is marked ReuseReg\n");
1340         return;
1341     }
1342
1343     // contained nodes are part of their parents for codegen purposes
1344     // ex : immediates, most LEAs
1345     if (treeNode->isContained())
1346     {
1347         return;
1348     }
1349
1350     switch (treeNode->gtOper)
1351     {
1352 #ifndef JIT32_GCENCODER
1353         case GT_START_NONGC:
1354             getEmitter()->emitDisableGC();
1355             break;
1356 #endif // !defined(JIT32_GCENCODER)
1357
1358         case GT_PROF_HOOK:
1359 #ifdef PROFILING_SUPPORTED
1360             // We should be seeing this only if profiler hook is needed
1361             noway_assert(compiler->compIsProfilerHookNeeded());
1362
1363             // Right now this node is used only for tail calls. In future if
1364             // we intend to use it for Enter or Leave hooks, add a data member
1365             // to this node indicating the kind of profiler hook. For example,
1366             // helper number can be used.
1367             genProfilingLeaveCallback(CORINFO_HELP_PROF_FCN_TAILCALL);
1368 #endif // PROFILING_SUPPORTED
1369             break;
1370
1371         case GT_LCLHEAP:
1372             genLclHeap(treeNode);
1373             break;
1374
1375         case GT_CNS_INT:
1376 #ifdef _TARGET_X86_
1377             assert(!treeNode->IsIconHandle(GTF_ICON_TLS_HDL));
1378 #endif // _TARGET_X86_
1379             __fallthrough;
1380
1381         case GT_CNS_DBL:
1382             genSetRegToConst(targetReg, targetType, treeNode);
1383             genProduceReg(treeNode);
1384             break;
1385
1386         case GT_NEG:
1387         case GT_NOT:
1388             if (varTypeIsFloating(targetType))
1389             {
1390                 assert(treeNode->gtOper == GT_NEG);
1391                 genSSE2BitwiseOp(treeNode);
1392             }
1393             else
1394             {
1395                 GenTreePtr operand = treeNode->gtGetOp1();
1396                 assert(operand->isUsedFromReg());
1397                 regNumber operandReg = genConsumeReg(operand);
1398
1399                 if (operandReg != targetReg)
1400                 {
1401                     inst_RV_RV(INS_mov, targetReg, operandReg, targetType);
1402                 }
1403
1404                 instruction ins = genGetInsForOper(treeNode->OperGet(), targetType);
1405                 inst_RV(ins, targetReg, targetType);
1406             }
1407             genProduceReg(treeNode);
1408             break;
1409
1410         case GT_OR:
1411         case GT_XOR:
1412         case GT_AND:
1413             assert(varTypeIsIntegralOrI(treeNode));
1414             __fallthrough;
1415
1416 #if !defined(_TARGET_64BIT_)
1417         case GT_ADD_LO:
1418         case GT_ADD_HI:
1419         case GT_SUB_LO:
1420         case GT_SUB_HI:
1421 #endif // !defined(_TARGET_64BIT_)
1422         case GT_ADD:
1423         case GT_SUB:
1424             genConsumeOperands(treeNode->AsOp());
1425             genCodeForBinary(treeNode);
1426             break;
1427
1428         case GT_LSH:
1429         case GT_RSH:
1430         case GT_RSZ:
1431         case GT_ROL:
1432         case GT_ROR:
1433             genCodeForShift(treeNode);
1434             // genCodeForShift() calls genProduceReg()
1435             break;
1436
1437 #if !defined(_TARGET_64BIT_)
1438         case GT_LSH_HI:
1439         case GT_RSH_LO:
1440             // TODO-X86-CQ: This only handles the case where the operand being shifted is in a register. We don't
1441             // need sourceHi to be always in reg in case of GT_LSH_HI (because it could be moved from memory to
1442             // targetReg if sourceHi is a memory operand). Similarly for GT_RSH_LO, sourceLo could be marked as
1443             // contained memory-op. Even if not a memory-op, we could mark it as reg-optional.
1444             genCodeForShiftLong(treeNode);
1445             break;
1446 #endif
1447
1448         case GT_CAST:
1449             if (varTypeIsFloating(targetType) && varTypeIsFloating(treeNode->gtOp.gtOp1))
1450             {
1451                 // Casts float/double <--> double/float
1452                 genFloatToFloatCast(treeNode);
1453             }
1454             else if (varTypeIsFloating(treeNode->gtOp.gtOp1))
1455             {
1456                 // Casts float/double --> int32/int64
1457                 genFloatToIntCast(treeNode);
1458             }
1459             else if (varTypeIsFloating(targetType))
1460             {
1461                 // Casts int32/uint32/int64/uint64 --> float/double
1462                 genIntToFloatCast(treeNode);
1463             }
1464             else
1465             {
1466                 // Casts int <--> int
1467                 genIntToIntCast(treeNode);
1468             }
1469             // The per-case functions call genProduceReg()
1470             break;
1471
1472         case GT_LCL_VAR:
1473         {
1474             // lcl_vars are not defs
1475             assert((treeNode->gtFlags & GTF_VAR_DEF) == 0);
1476
1477             GenTreeLclVarCommon* lcl            = treeNode->AsLclVarCommon();
1478             bool                 isRegCandidate = compiler->lvaTable[lcl->gtLclNum].lvIsRegCandidate();
1479
1480             if (isRegCandidate && !(treeNode->gtFlags & GTF_VAR_DEATH))
1481             {
1482                 assert(treeNode->InReg() || (treeNode->gtFlags & GTF_SPILLED));
1483             }
1484
1485             // If this is a register candidate that has been spilled, genConsumeReg() will
1486             // reload it at the point of use.  Otherwise, if it's not in a register, we load it here.
1487
1488             if (!treeNode->InReg() && !(treeNode->gtFlags & GTF_SPILLED))
1489             {
1490                 assert(!isRegCandidate);
1491 #if defined(FEATURE_SIMD) && defined(_TARGET_X86_)
1492                 // Loading of TYP_SIMD12 (i.e. Vector3) variable
1493                 if (treeNode->TypeGet() == TYP_SIMD12)
1494                 {
1495                     genLoadLclTypeSIMD12(treeNode);
1496                     break;
1497                 }
1498 #endif // defined(FEATURE_SIMD) && defined(_TARGET_X86_)
1499
1500                 emit->emitIns_R_S(ins_Load(treeNode->TypeGet(), compiler->isSIMDTypeLocalAligned(lcl->gtLclNum)),
1501                                   emitTypeSize(treeNode), treeNode->gtRegNum, lcl->gtLclNum, 0);
1502                 genProduceReg(treeNode);
1503             }
1504         }
1505         break;
1506
1507         case GT_LCL_FLD_ADDR:
1508         case GT_LCL_VAR_ADDR:
1509             // Address of a local var.  This by itself should never be allocated a register.
1510             // If it is worth storing the address in a register then it should be cse'ed into
1511             // a temp and that would be allocated a register.
1512             noway_assert(targetType == TYP_BYREF);
1513             noway_assert(!treeNode->InReg());
1514
1515             inst_RV_TT(INS_lea, targetReg, treeNode, 0, EA_BYREF);
1516             genProduceReg(treeNode);
1517             break;
1518
1519         case GT_LCL_FLD:
1520         {
1521             noway_assert(targetType != TYP_STRUCT);
1522             noway_assert(treeNode->gtRegNum != REG_NA);
1523
1524 #ifdef FEATURE_SIMD
1525             // Loading of TYP_SIMD12 (i.e. Vector3) field
1526             if (treeNode->TypeGet() == TYP_SIMD12)
1527             {
1528                 genLoadLclTypeSIMD12(treeNode);
1529                 break;
1530             }
1531 #endif
1532
1533             emitAttr size   = emitTypeSize(targetType);
1534             unsigned offs   = treeNode->gtLclFld.gtLclOffs;
1535             unsigned varNum = treeNode->gtLclVarCommon.gtLclNum;
1536             assert(varNum < compiler->lvaCount);
1537
1538             emit->emitIns_R_S(ins_Move_Extend(targetType, treeNode->InReg()), size, targetReg, varNum, offs);
1539         }
1540             genProduceReg(treeNode);
1541             break;
1542
1543         case GT_STORE_LCL_FLD:
1544         {
1545             noway_assert(targetType != TYP_STRUCT);
1546             noway_assert(!treeNode->InReg());
1547             assert(!varTypeIsFloating(targetType) || (targetType == treeNode->gtGetOp1()->TypeGet()));
1548
1549 #ifdef FEATURE_SIMD
1550             // storing of TYP_SIMD12 (i.e. Vector3) field
1551             if (treeNode->TypeGet() == TYP_SIMD12)
1552             {
1553                 genStoreLclTypeSIMD12(treeNode);
1554                 break;
1555             }
1556 #endif // FEATURE_SIMD
1557
1558             GenTreePtr op1 = treeNode->gtGetOp1();
1559             genConsumeRegs(op1);
1560             emit->emitInsBinary(ins_Store(targetType), emitTypeSize(treeNode), treeNode, op1);
1561
1562             genUpdateLife(treeNode);
1563         }
1564         break;
1565
1566         case GT_STORE_LCL_VAR:
1567         {
1568             GenTreePtr op1 = treeNode->gtGetOp1();
1569
1570             // var = call, where call returns a multi-reg return value
1571             // case is handled separately.
1572             if (op1->gtSkipReloadOrCopy()->IsMultiRegCall())
1573             {
1574                 genMultiRegCallStoreToLocal(treeNode);
1575             }
1576             else
1577             {
1578                 noway_assert(targetType != TYP_STRUCT);
1579                 assert(!varTypeIsFloating(targetType) || (targetType == treeNode->gtGetOp1()->TypeGet()));
1580
1581                 unsigned   lclNum = treeNode->AsLclVarCommon()->gtLclNum;
1582                 LclVarDsc* varDsc = &(compiler->lvaTable[lclNum]);
1583
1584                 // Ensure that lclVar nodes are typed correctly.
1585                 assert(!varDsc->lvNormalizeOnStore() || treeNode->TypeGet() == genActualType(varDsc->TypeGet()));
1586
1587 #if !defined(_TARGET_64BIT_)
1588                 if (treeNode->TypeGet() == TYP_LONG)
1589                 {
1590                     genStoreLongLclVar(treeNode);
1591                     break;
1592                 }
1593 #endif // !defined(_TARGET_64BIT_)
1594
1595 #ifdef FEATURE_SIMD
1596                 // storing of TYP_SIMD12 (i.e. Vector3) field
1597                 if (treeNode->TypeGet() == TYP_SIMD12)
1598                 {
1599                     genStoreLclTypeSIMD12(treeNode);
1600                     break;
1601                 }
1602
1603                 if (varTypeIsSIMD(targetType) && (targetReg != REG_NA) && op1->IsCnsIntOrI())
1604                 {
1605                     // This is only possible for a zero-init.
1606                     noway_assert(op1->IsIntegralConst(0));
1607                     genSIMDZero(targetType, varDsc->lvBaseType, targetReg);
1608                     genProduceReg(treeNode);
1609                     break;
1610                 }
1611 #endif // FEATURE_SIMD
1612
1613                 genConsumeRegs(op1);
1614
1615                 if (treeNode->gtRegNum == REG_NA)
1616                 {
1617                     // stack store
1618                     emit->emitInsMov(ins_Store(targetType, compiler->isSIMDTypeLocalAligned(lclNum)),
1619                                      emitTypeSize(targetType), treeNode);
1620                     varDsc->lvRegNum = REG_STK;
1621                 }
1622                 else
1623                 {
1624                     // Look for the case where we have a constant zero which we've marked for reuse,
1625                     // but which isn't actually in the register we want.  In that case, it's better to create
1626                     // zero in the target register, because an xor is smaller than a copy. Note that we could
1627                     // potentially handle this in the register allocator, but we can't always catch it there
1628                     // because the target may not have a register allocated for it yet.
1629                     if (op1->isUsedFromReg() && (op1->gtRegNum != treeNode->gtRegNum) &&
1630                         (op1->IsIntegralConst(0) || op1->IsFPZero()))
1631                     {
1632                         op1->gtRegNum = REG_NA;
1633                         op1->ResetReuseRegVal();
1634                     }
1635
1636                     if (!op1->isUsedFromReg())
1637                     {
1638                         // Currently, we assume that the non-reg source of a GT_STORE_LCL_VAR writing to a register
1639                         // must be a constant. However, in the future we might want to support an operand used from
1640                         // memory.  This is a bit tricky because we have to decide it can be used from memory before
1641                         // register allocation,
1642                         // and this would be a case where, once that's done, we need to mark that node as always
1643                         // requiring a register - which we always assume now anyway, but once we "optimize" that
1644                         // we'll have to take cases like this into account.
1645                         assert((op1->gtRegNum == REG_NA) && op1->OperIsConst());
1646                         genSetRegToConst(treeNode->gtRegNum, targetType, op1);
1647                     }
1648                     else if (op1->gtRegNum != treeNode->gtRegNum)
1649                     {
1650                         assert(op1->gtRegNum != REG_NA);
1651                         emit->emitInsBinary(ins_Move_Extend(targetType, true), emitTypeSize(treeNode), treeNode, op1);
1652                     }
1653                 }
1654             }
1655
1656             if (treeNode->gtRegNum != REG_NA)
1657             {
1658                 genProduceReg(treeNode);
1659             }
1660         }
1661         break;
1662
1663         case GT_RETFILT:
1664             // A void GT_RETFILT is the end of a finally. For non-void filter returns we need to load the result in
1665             // the return register, if it's not already there. The processing is the same as GT_RETURN.
1666             if (targetType != TYP_VOID)
1667             {
1668                 // For filters, the IL spec says the result is type int32. Further, the only specified legal values
1669                 // are 0 or 1, with the use of other values "undefined".
1670                 assert(targetType == TYP_INT);
1671             }
1672
1673             __fallthrough;
1674
1675         case GT_RETURN:
1676             genReturn(treeNode);
1677             break;
1678
1679         case GT_LEA:
1680         {
1681             // if we are here, it is the case where there is an LEA that cannot
1682             // be folded into a parent instruction
1683             GenTreeAddrMode* lea = treeNode->AsAddrMode();
1684             genLeaInstruction(lea);
1685         }
1686         // genLeaInstruction calls genProduceReg()
1687         break;
1688
1689         case GT_IND:
1690         {
1691 #ifdef FEATURE_SIMD
1692             // Handling of Vector3 type values loaded through indirection.
1693             if (treeNode->TypeGet() == TYP_SIMD12)
1694             {
1695                 genLoadIndTypeSIMD12(treeNode);
1696                 break;
1697             }
1698 #endif // FEATURE_SIMD
1699
1700             GenTree* addr = treeNode->AsIndir()->Addr();
1701             if (addr->IsCnsIntOrI() && addr->IsIconHandle(GTF_ICON_TLS_HDL))
1702             {
1703                 noway_assert(EA_ATTR(genTypeSize(treeNode->gtType)) == EA_PTRSIZE);
1704                 emit->emitIns_R_C(ins_Load(TYP_I_IMPL), EA_PTRSIZE, treeNode->gtRegNum, FLD_GLOBAL_FS,
1705                                   (int)addr->gtIntCon.gtIconVal);
1706             }
1707             else
1708             {
1709                 genConsumeAddress(addr);
1710                 emit->emitInsMov(ins_Load(treeNode->TypeGet()), emitTypeSize(treeNode), treeNode);
1711             }
1712             genProduceReg(treeNode);
1713         }
1714         break;
1715
1716         case GT_MULHI:
1717 #ifdef _TARGET_X86_
1718         case GT_MUL_LONG:
1719 #endif
1720             genCodeForMulHi(treeNode->AsOp());
1721             genProduceReg(treeNode);
1722             break;
1723
1724         case GT_MUL:
1725         {
1726             instruction ins;
1727             emitAttr    size                  = emitTypeSize(treeNode);
1728             bool        isUnsignedMultiply    = ((treeNode->gtFlags & GTF_UNSIGNED) != 0);
1729             bool        requiresOverflowCheck = treeNode->gtOverflowEx();
1730
1731             GenTree* op1 = treeNode->gtGetOp1();
1732             GenTree* op2 = treeNode->gtGetOp2();
1733
1734             // there are 3 forms of x64 multiply:
1735             // 1-op form with 128 result:  RDX:RAX = RAX * rm
1736             // 2-op form: reg *= rm
1737             // 3-op form: reg = rm * imm
1738
1739             genConsumeOperands(treeNode->AsOp());
1740
1741             // This matches the 'mul' lowering in Lowering::SetMulOpCounts()
1742             //
1743             // immOp :: Only one operand can be an immediate
1744             // rmOp  :: Only one operand can be a memory op.
1745             // regOp :: A register op (especially the operand that matches 'targetReg')
1746             //          (can be nullptr when we have both a memory op and an immediate op)
1747
1748             GenTree* immOp = nullptr;
1749             GenTree* rmOp  = op1;
1750             GenTree* regOp;
1751
1752             if (op2->isContainedIntOrIImmed())
1753             {
1754                 immOp = op2;
1755             }
1756             else if (op1->isContainedIntOrIImmed())
1757             {
1758                 immOp = op1;
1759                 rmOp  = op2;
1760             }
1761
1762             if (immOp != nullptr)
1763             {
1764                 // This must be a non-floating point operation.
1765                 assert(!varTypeIsFloating(treeNode));
1766
1767                 // CQ: When possible use LEA for mul by imm 3, 5 or 9
1768                 ssize_t imm = immOp->AsIntConCommon()->IconValue();
1769
1770                 if (!requiresOverflowCheck && rmOp->isUsedFromReg() && ((imm == 3) || (imm == 5) || (imm == 9)))
1771                 {
1772                     // We will use the LEA instruction to perform this multiply
1773                     // Note that an LEA with base=x, index=x and scale=(imm-1) computes x*imm when imm=3,5 or 9.
1774                     unsigned int scale = (unsigned int)(imm - 1);
1775                     getEmitter()->emitIns_R_ARX(INS_lea, size, targetReg, rmOp->gtRegNum, rmOp->gtRegNum, scale, 0);
1776                 }
1777                 else
1778                 {
1779                     // use the 3-op form with immediate
1780                     ins = getEmitter()->inst3opImulForReg(targetReg);
1781                     emit->emitInsBinary(ins, size, rmOp, immOp);
1782                 }
1783             }
1784             else // we have no contained immediate operand
1785             {
1786                 regOp = op1;
1787                 rmOp  = op2;
1788
1789                 regNumber mulTargetReg = targetReg;
1790                 if (isUnsignedMultiply && requiresOverflowCheck)
1791                 {
1792                     ins          = INS_mulEAX;
1793                     mulTargetReg = REG_RAX;
1794                 }
1795                 else
1796                 {
1797                     ins = genGetInsForOper(GT_MUL, targetType);
1798                 }
1799
1800                 // Set rmOp to the memory operand (if any)
1801                 // or set regOp to the op2 when it has the matching target register for our multiply op
1802                 //
1803                 if (op1->isUsedFromMemory() || (op2->isUsedFromReg() && (op2->gtRegNum == mulTargetReg)))
1804                 {
1805                     regOp = op2;
1806                     rmOp  = op1;
1807                 }
1808                 assert(regOp->isUsedFromReg());
1809
1810                 // Setup targetReg when neither of the source operands was a matching register
1811                 if (regOp->gtRegNum != mulTargetReg)
1812                 {
1813                     inst_RV_RV(ins_Copy(targetType), mulTargetReg, regOp->gtRegNum, targetType);
1814                 }
1815
1816                 emit->emitInsBinary(ins, size, treeNode, rmOp);
1817
1818                 // Move the result to the desired register, if necessary
1819                 if ((ins == INS_mulEAX) && (targetReg != REG_RAX))
1820                 {
1821                     inst_RV_RV(INS_mov, targetReg, REG_RAX, targetType);
1822                 }
1823             }
1824
1825             if (requiresOverflowCheck)
1826             {
1827                 // Overflow checking is only used for non-floating point types
1828                 noway_assert(!varTypeIsFloating(treeNode));
1829
1830                 genCheckOverflow(treeNode);
1831             }
1832         }
1833             genProduceReg(treeNode);
1834             break;
1835
1836         case GT_MOD:
1837         case GT_UDIV:
1838         case GT_UMOD:
1839             // We shouldn't be seeing GT_MOD on float/double args as it should get morphed into a
1840             // helper call by front-end.  Similarly we shouldn't be seeing GT_UDIV and GT_UMOD
1841             // on float/double args.
1842             noway_assert(!varTypeIsFloating(treeNode));
1843             __fallthrough;
1844
1845         case GT_DIV:
1846             genCodeForDivMod(treeNode->AsOp());
1847             break;
1848
1849         case GT_INTRINSIC:
1850             genIntrinsic(treeNode);
1851             break;
1852
1853 #ifdef FEATURE_SIMD
1854         case GT_SIMD:
1855             genSIMDIntrinsic(treeNode->AsSIMD());
1856             break;
1857 #endif // FEATURE_SIMD
1858
1859         case GT_CKFINITE:
1860             genCkfinite(treeNode);
1861             break;
1862
1863         case GT_EQ:
1864         case GT_NE:
1865         case GT_LT:
1866         case GT_LE:
1867         case GT_GE:
1868         case GT_GT:
1869         case GT_TEST_EQ:
1870         case GT_TEST_NE:
1871         {
1872             // TODO-XArch-CQ: Check if we can use the currently set flags.
1873             // TODO-XArch-CQ: Check for the case where we can simply transfer the carry bit to a register
1874             //         (signed < or >= where targetReg != REG_NA)
1875
1876             GenTreePtr op1     = treeNode->gtGetOp1();
1877             var_types  op1Type = op1->TypeGet();
1878
1879             if (varTypeIsFloating(op1Type))
1880             {
1881                 genCompareFloat(treeNode);
1882             }
1883 #if !defined(_TARGET_64BIT_)
1884             // X86 Long comparison
1885             else if (varTypeIsLong(op1Type))
1886             {
1887 #ifdef DEBUG
1888                 // The result of an unlowered long compare on a 32-bit target must either be
1889                 // a) materialized into a register, or
1890                 // b) unused.
1891                 //
1892                 // A long compare that has a result that is used but not materialized into a register should
1893                 // have been handled by Lowering::LowerCompare.
1894
1895                 LIR::Use use;
1896                 assert((treeNode->gtRegNum != REG_NA) || !LIR::AsRange(compiler->compCurBB).TryGetUse(treeNode, &use));
1897 #endif
1898                 genCompareLong(treeNode);
1899             }
1900 #endif // !defined(_TARGET_64BIT_)
1901             else
1902             {
1903                 genCompareInt(treeNode);
1904             }
1905         }
1906         break;
1907
1908         case GT_JTRUE:
1909             genCodeForJumpTrue(treeNode);
1910             break;
1911
1912         case GT_JCC:
1913         {
1914             GenTreeJumpCC* jcc = treeNode->AsJumpCC();
1915
1916             assert(compiler->compCurBB->bbJumpKind == BBJ_COND);
1917
1918             CompareKind  compareKind = ((jcc->gtFlags & GTF_UNSIGNED) != 0) ? CK_UNSIGNED : CK_SIGNED;
1919             emitJumpKind jumpKind    = genJumpKindForOper(jcc->gtCondition, compareKind);
1920
1921             inst_JMP(jumpKind, compiler->compCurBB->bbJumpDest);
1922         }
1923         break;
1924
1925         case GT_RETURNTRAP:
1926         {
1927             // this is nothing but a conditional call to CORINFO_HELP_STOP_FOR_GC
1928             // based on the contents of 'data'
1929
1930             GenTree* data = treeNode->gtOp.gtOp1;
1931             genConsumeRegs(data);
1932             GenTreeIntCon cns = intForm(TYP_INT, 0);
1933             emit->emitInsBinary(INS_cmp, emitTypeSize(TYP_INT), data, &cns);
1934
1935             BasicBlock* skipLabel = genCreateTempLabel();
1936
1937             emitJumpKind jmpEqual = genJumpKindForOper(GT_EQ, CK_SIGNED);
1938             inst_JMP(jmpEqual, skipLabel);
1939
1940             // emit the call to the EE-helper that stops for GC (or other reasons)
1941             regNumber tmpReg = treeNode->GetSingleTempReg();
1942             assert(genIsValidIntReg(tmpReg));
1943
1944             genEmitHelperCall(CORINFO_HELP_STOP_FOR_GC, 0, EA_UNKNOWN, tmpReg);
1945             genDefineTempLabel(skipLabel);
1946         }
1947         break;
1948
1949         case GT_STOREIND:
1950             genStoreInd(treeNode);
1951             break;
1952
1953         case GT_COPY:
1954             // This is handled at the time we call genConsumeReg() on the GT_COPY
1955             break;
1956
1957         case GT_SWAP:
1958         {
1959             // Swap is only supported for lclVar operands that are enregistered
1960             // We do not consume or produce any registers.  Both operands remain enregistered.
1961             // However, the gc-ness may change.
1962             assert(genIsRegCandidateLocal(treeNode->gtOp.gtOp1) && genIsRegCandidateLocal(treeNode->gtOp.gtOp2));
1963
1964             GenTreeLclVarCommon* lcl1    = treeNode->gtOp.gtOp1->AsLclVarCommon();
1965             LclVarDsc*           varDsc1 = &(compiler->lvaTable[lcl1->gtLclNum]);
1966             var_types            type1   = varDsc1->TypeGet();
1967             GenTreeLclVarCommon* lcl2    = treeNode->gtOp.gtOp2->AsLclVarCommon();
1968             LclVarDsc*           varDsc2 = &(compiler->lvaTable[lcl2->gtLclNum]);
1969             var_types            type2   = varDsc2->TypeGet();
1970
1971             // We must have both int or both fp regs
1972             assert(!varTypeIsFloating(type1) || varTypeIsFloating(type2));
1973
1974             // FP swap is not yet implemented (and should have NYI'd in LSRA)
1975             assert(!varTypeIsFloating(type1));
1976
1977             regNumber oldOp1Reg     = lcl1->gtRegNum;
1978             regMaskTP oldOp1RegMask = genRegMask(oldOp1Reg);
1979             regNumber oldOp2Reg     = lcl2->gtRegNum;
1980             regMaskTP oldOp2RegMask = genRegMask(oldOp2Reg);
1981
1982             // We don't call genUpdateVarReg because we don't have a tree node with the new register.
1983             varDsc1->lvRegNum = oldOp2Reg;
1984             varDsc2->lvRegNum = oldOp1Reg;
1985
1986             // Do the xchg
1987             emitAttr size = EA_PTRSIZE;
1988             if (varTypeGCtype(type1) != varTypeGCtype(type2))
1989             {
1990                 // If the type specified to the emitter is a GC type, it will swap the GC-ness of the registers.
1991                 // Otherwise it will leave them alone, which is correct if they have the same GC-ness.
1992                 size = EA_GCREF;
1993             }
1994             inst_RV_RV(INS_xchg, oldOp1Reg, oldOp2Reg, TYP_I_IMPL, size);
1995
1996             // Update the gcInfo.
1997             // Manually remove these regs for the gc sets (mostly to avoid confusing duplicative dump output)
1998             gcInfo.gcRegByrefSetCur &= ~(oldOp1RegMask | oldOp2RegMask);
1999             gcInfo.gcRegGCrefSetCur &= ~(oldOp1RegMask | oldOp2RegMask);
2000
2001             // gcMarkRegPtrVal will do the appropriate thing for non-gc types.
2002             // It will also dump the updates.
2003             gcInfo.gcMarkRegPtrVal(oldOp2Reg, type1);
2004             gcInfo.gcMarkRegPtrVal(oldOp1Reg, type2);
2005         }
2006         break;
2007
2008         case GT_LIST:
2009         case GT_FIELD_LIST:
2010         case GT_ARGPLACE:
2011             // Nothing to do
2012             break;
2013
2014         case GT_PUTARG_STK:
2015             genPutArgStk(treeNode->AsPutArgStk());
2016             break;
2017
2018         case GT_PUTARG_REG:
2019         {
2020 #ifndef FEATURE_UNIX_AMD64_STRUCT_PASSING
2021             noway_assert(targetType != TYP_STRUCT);
2022 #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
2023             // commas show up here commonly, as part of a nullchk operation
2024             GenTree* op1 = treeNode->gtOp.gtOp1;
2025             // If child node is not already in the register we need, move it
2026             genConsumeReg(op1);
2027             if (treeNode->gtRegNum != op1->gtRegNum)
2028             {
2029                 inst_RV_RV(ins_Copy(targetType), treeNode->gtRegNum, op1->gtRegNum, targetType);
2030             }
2031             genProduceReg(treeNode);
2032         }
2033         break;
2034
2035         case GT_CALL:
2036             genCallInstruction(treeNode->AsCall());
2037             break;
2038
2039         case GT_JMP:
2040             genJmpMethod(treeNode);
2041             break;
2042
2043         case GT_LOCKADD:
2044         case GT_XCHG:
2045         case GT_XADD:
2046             genLockedInstructions(treeNode->AsOp());
2047             break;
2048
2049         case GT_MEMORYBARRIER:
2050             instGen_MemoryBarrier();
2051             break;
2052
2053         case GT_CMPXCHG:
2054         {
2055             GenTreePtr location  = treeNode->gtCmpXchg.gtOpLocation;  // arg1
2056             GenTreePtr value     = treeNode->gtCmpXchg.gtOpValue;     // arg2
2057             GenTreePtr comparand = treeNode->gtCmpXchg.gtOpComparand; // arg3
2058
2059             assert(location->gtRegNum != REG_NA && location->gtRegNum != REG_RAX);
2060             assert(value->gtRegNum != REG_NA && value->gtRegNum != REG_RAX);
2061
2062             genConsumeReg(location);
2063             genConsumeReg(value);
2064             genConsumeReg(comparand);
2065             // comparand goes to RAX;
2066             // Note that we must issue this move after the genConsumeRegs(), in case any of the above
2067             // have a GT_COPY from RAX.
2068             if (comparand->gtRegNum != REG_RAX)
2069             {
2070                 inst_RV_RV(ins_Copy(comparand->TypeGet()), REG_RAX, comparand->gtRegNum, comparand->TypeGet());
2071             }
2072
2073             // location is Rm
2074             instGen(INS_lock);
2075
2076             emit->emitIns_AR_R(INS_cmpxchg, emitTypeSize(targetType), value->gtRegNum, location->gtRegNum, 0);
2077
2078             // Result is in RAX
2079             if (targetReg != REG_RAX)
2080             {
2081                 inst_RV_RV(ins_Copy(targetType), targetReg, REG_RAX, targetType);
2082             }
2083         }
2084             genProduceReg(treeNode);
2085             break;
2086
2087         case GT_RELOAD:
2088             // do nothing - reload is just a marker.
2089             // The parent node will call genConsumeReg on this which will trigger the unspill of this node's child
2090             // into the register specified in this node.
2091             break;
2092
2093         case GT_NOP:
2094             break;
2095
2096         case GT_NO_OP:
2097             if (treeNode->gtFlags & GTF_NO_OP_NO)
2098             {
2099                 noway_assert(!"GTF_NO_OP_NO should not be set");
2100             }
2101             else
2102             {
2103                 getEmitter()->emitIns_Nop(1);
2104             }
2105             break;
2106
2107         case GT_ARR_BOUNDS_CHECK:
2108 #ifdef FEATURE_SIMD
2109         case GT_SIMD_CHK:
2110 #endif // FEATURE_SIMD
2111             genRangeCheck(treeNode);
2112             break;
2113
2114         case GT_PHYSREG:
2115             if (treeNode->gtRegNum != treeNode->AsPhysReg()->gtSrcReg)
2116             {
2117                 inst_RV_RV(INS_mov, treeNode->gtRegNum, treeNode->AsPhysReg()->gtSrcReg, targetType);
2118
2119                 genTransferRegGCState(treeNode->gtRegNum, treeNode->AsPhysReg()->gtSrcReg);
2120             }
2121             genProduceReg(treeNode);
2122             break;
2123
2124         case GT_PHYSREGDST:
2125             break;
2126
2127         case GT_NULLCHECK:
2128         {
2129             assert(treeNode->gtOp.gtOp1->isUsedFromReg());
2130             regNumber reg = genConsumeReg(treeNode->gtOp.gtOp1);
2131             emit->emitIns_AR_R(INS_cmp, EA_4BYTE, reg, reg, 0);
2132         }
2133         break;
2134
2135         case GT_CATCH_ARG:
2136
2137             noway_assert(handlerGetsXcptnObj(compiler->compCurBB->bbCatchTyp));
2138
2139             /* Catch arguments get passed in a register. genCodeForBBlist()
2140                would have marked it as holding a GC object, but not used. */
2141
2142             noway_assert(gcInfo.gcRegGCrefSetCur & RBM_EXCEPTION_OBJECT);
2143             genConsumeReg(treeNode);
2144             break;
2145
2146 #if !FEATURE_EH_FUNCLETS
2147         case GT_END_LFIN:
2148
2149             // Have to clear the ShadowSP of the nesting level which encloses the finally. Generates:
2150             //     mov dword ptr [ebp-0xC], 0  // for some slot of the ShadowSP local var
2151
2152             unsigned finallyNesting;
2153             finallyNesting = treeNode->gtVal.gtVal1;
2154             noway_assert(treeNode->gtVal.gtVal1 < compiler->compHndBBtabCount);
2155             noway_assert(finallyNesting < compiler->compHndBBtabCount);
2156
2157             // The last slot is reserved for ICodeManager::FixContext(ppEndRegion)
2158             unsigned filterEndOffsetSlotOffs;
2159             PREFIX_ASSUME(compiler->lvaLclSize(compiler->lvaShadowSPslotsVar) >
2160                           TARGET_POINTER_SIZE); // below doesn't underflow.
2161             filterEndOffsetSlotOffs =
2162                 (unsigned)(compiler->lvaLclSize(compiler->lvaShadowSPslotsVar) - TARGET_POINTER_SIZE);
2163
2164             unsigned curNestingSlotOffs;
2165             curNestingSlotOffs = filterEndOffsetSlotOffs - ((finallyNesting + 1) * TARGET_POINTER_SIZE);
2166             instGen_Store_Imm_Into_Lcl(TYP_I_IMPL, EA_PTRSIZE, 0, compiler->lvaShadowSPslotsVar, curNestingSlotOffs);
2167             break;
2168 #endif // !FEATURE_EH_FUNCLETS
2169
2170         case GT_PINVOKE_PROLOG:
2171             noway_assert(((gcInfo.gcRegGCrefSetCur | gcInfo.gcRegByrefSetCur) & ~fullIntArgRegMask()) == 0);
2172
2173             // the runtime side requires the codegen here to be consistent
2174             emit->emitDisableRandomNops();
2175             break;
2176
2177         case GT_LABEL:
2178             genPendingCallLabel       = genCreateTempLabel();
2179             treeNode->gtLabel.gtLabBB = genPendingCallLabel;
2180             emit->emitIns_R_L(INS_lea, EA_PTR_DSP_RELOC, genPendingCallLabel, treeNode->gtRegNum);
2181             break;
2182
2183         case GT_STORE_OBJ:
2184             if (treeNode->OperIsCopyBlkOp() && !treeNode->AsBlk()->gtBlkOpGcUnsafe)
2185             {
2186                 assert(treeNode->AsObj()->gtGcPtrCount != 0);
2187                 genCodeForCpObj(treeNode->AsObj());
2188                 break;
2189             }
2190             __fallthrough;
2191
2192         case GT_STORE_DYN_BLK:
2193         case GT_STORE_BLK:
2194             genCodeForStoreBlk(treeNode->AsBlk());
2195             break;
2196
2197         case GT_JMPTABLE:
2198             genJumpTable(treeNode);
2199             break;
2200
2201         case GT_SWITCH_TABLE:
2202             genTableBasedSwitch(treeNode);
2203             break;
2204
2205         case GT_ARR_INDEX:
2206             genCodeForArrIndex(treeNode->AsArrIndex());
2207             break;
2208
2209         case GT_ARR_OFFSET:
2210             genCodeForArrOffset(treeNode->AsArrOffs());
2211             break;
2212
2213         case GT_CLS_VAR_ADDR:
2214             getEmitter()->emitIns_R_C(INS_lea, EA_PTRSIZE, targetReg, treeNode->gtClsVar.gtClsVarHnd, 0);
2215             genProduceReg(treeNode);
2216             break;
2217
2218 #if !defined(_TARGET_64BIT_)
2219         case GT_LONG:
2220             assert(treeNode->isUsedFromReg());
2221             genConsumeRegs(treeNode);
2222             break;
2223 #endif
2224
2225         case GT_IL_OFFSET:
2226             // Do nothing; these nodes are simply markers for debug info.
2227             break;
2228
2229         default:
2230         {
2231 #ifdef DEBUG
2232             char message[256];
2233             _snprintf_s(message, _countof(message), _TRUNCATE, "Unimplemented node type %s\n",
2234                         GenTree::NodeName(treeNode->OperGet()));
2235 #endif
2236             assert(!"Unknown node in codegen");
2237         }
2238         break;
2239     }
2240 }
2241
2242 //----------------------------------------------------------------------------------
2243 // genMultiRegCallStoreToLocal: store multi-reg return value of a call node to a local
2244 //
2245 // Arguments:
2246 //    treeNode  -  Gentree of GT_STORE_LCL_VAR
2247 //
2248 // Return Value:
2249 //    None
2250 //
2251 // Assumption:
2252 //    The child of store is a multi-reg call node.
2253 //    genProduceReg() on treeNode is made by caller of this routine.
2254 //
2255 void CodeGen::genMultiRegCallStoreToLocal(GenTreePtr treeNode)
2256 {
2257     assert(treeNode->OperGet() == GT_STORE_LCL_VAR);
2258
2259 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
2260     // Structs of size >=9 and <=16 are returned in two return registers on x64 Unix.
2261     assert(varTypeIsStruct(treeNode));
2262
2263     // Assumption: current x64 Unix implementation requires that a multi-reg struct
2264     // var in 'var = call' is flagged as lvIsMultiRegRet to prevent it from
2265     // being struct promoted.
2266     unsigned   lclNum = treeNode->AsLclVarCommon()->gtLclNum;
2267     LclVarDsc* varDsc = &(compiler->lvaTable[lclNum]);
2268     noway_assert(varDsc->lvIsMultiRegRet);
2269
2270     GenTree*     op1       = treeNode->gtGetOp1();
2271     GenTree*     actualOp1 = op1->gtSkipReloadOrCopy();
2272     GenTreeCall* call      = actualOp1->AsCall();
2273     assert(call->HasMultiRegRetVal());
2274
2275     genConsumeRegs(op1);
2276
2277     ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc();
2278     assert(retTypeDesc->GetReturnRegCount() == MAX_RET_REG_COUNT);
2279     unsigned regCount = retTypeDesc->GetReturnRegCount();
2280
2281     if (treeNode->gtRegNum != REG_NA)
2282     {
2283         // Right now the only enregistrable structs supported are SIMD types.
2284         assert(varTypeIsSIMD(treeNode));
2285         assert(varTypeIsFloating(retTypeDesc->GetReturnRegType(0)));
2286         assert(varTypeIsFloating(retTypeDesc->GetReturnRegType(1)));
2287
2288         // This is a case of two 8-bytes that comprise the operand is in
2289         // two different xmm registers and needs to assembled into a single
2290         // xmm register.
2291         regNumber targetReg = treeNode->gtRegNum;
2292         regNumber reg0      = call->GetRegNumByIdx(0);
2293         regNumber reg1      = call->GetRegNumByIdx(1);
2294
2295         if (op1->IsCopyOrReload())
2296         {
2297             // GT_COPY/GT_RELOAD will have valid reg for those positions
2298             // that need to be copied or reloaded.
2299             regNumber reloadReg = op1->AsCopyOrReload()->GetRegNumByIdx(0);
2300             if (reloadReg != REG_NA)
2301             {
2302                 reg0 = reloadReg;
2303             }
2304
2305             reloadReg = op1->AsCopyOrReload()->GetRegNumByIdx(1);
2306             if (reloadReg != REG_NA)
2307             {
2308                 reg1 = reloadReg;
2309             }
2310         }
2311
2312         if (targetReg != reg0 && targetReg != reg1)
2313         {
2314             // Copy reg0 into targetReg and let it to be handled by one
2315             // of the cases below.
2316             inst_RV_RV(ins_Copy(TYP_DOUBLE), targetReg, reg0, TYP_DOUBLE);
2317             targetReg = reg0;
2318         }
2319
2320         if (targetReg == reg0)
2321         {
2322             // targeReg[63:0] = targetReg[63:0]
2323             // targetReg[127:64] = reg1[127:64]
2324             inst_RV_RV_IV(INS_shufpd, EA_16BYTE, targetReg, reg1, 0x00);
2325         }
2326         else
2327         {
2328             assert(targetReg == reg1);
2329
2330             // We need two shuffles to achieve this
2331             // First:
2332             // targeReg[63:0] = targetReg[63:0]
2333             // targetReg[127:64] = reg0[63:0]
2334             //
2335             // Second:
2336             // targeReg[63:0] = targetReg[127:64]
2337             // targetReg[127:64] = targetReg[63:0]
2338             //
2339             // Essentially copy low 8-bytes from reg0 to high 8-bytes of targetReg
2340             // and next swap low and high 8-bytes of targetReg to have them
2341             // rearranged in the right order.
2342             inst_RV_RV_IV(INS_shufpd, EA_16BYTE, targetReg, reg0, 0x00);
2343             inst_RV_RV_IV(INS_shufpd, EA_16BYTE, targetReg, targetReg, 0x01);
2344         }
2345     }
2346     else
2347     {
2348         // Stack store
2349         int offset = 0;
2350         for (unsigned i = 0; i < regCount; ++i)
2351         {
2352             var_types type = retTypeDesc->GetReturnRegType(i);
2353             regNumber reg  = call->GetRegNumByIdx(i);
2354             if (op1->IsCopyOrReload())
2355             {
2356                 // GT_COPY/GT_RELOAD will have valid reg for those positions
2357                 // that need to be copied or reloaded.
2358                 regNumber reloadReg = op1->AsCopyOrReload()->GetRegNumByIdx(i);
2359                 if (reloadReg != REG_NA)
2360                 {
2361                     reg = reloadReg;
2362                 }
2363             }
2364
2365             assert(reg != REG_NA);
2366             getEmitter()->emitIns_S_R(ins_Store(type), emitTypeSize(type), reg, lclNum, offset);
2367             offset += genTypeSize(type);
2368         }
2369
2370         varDsc->lvRegNum = REG_STK;
2371     }
2372 #elif defined(_TARGET_X86_)
2373     // Longs are returned in two return registers on x86.
2374     assert(varTypeIsLong(treeNode));
2375
2376     // Assumption: current x86 implementation requires that a multi-reg long
2377     // var in 'var = call' is flagged as lvIsMultiRegRet to prevent it from
2378     // being promoted.
2379     unsigned   lclNum = treeNode->AsLclVarCommon()->gtLclNum;
2380     LclVarDsc* varDsc = &(compiler->lvaTable[lclNum]);
2381     noway_assert(varDsc->lvIsMultiRegRet);
2382
2383     GenTree*     op1       = treeNode->gtGetOp1();
2384     GenTree*     actualOp1 = op1->gtSkipReloadOrCopy();
2385     GenTreeCall* call      = actualOp1->AsCall();
2386     assert(call->HasMultiRegRetVal());
2387
2388     genConsumeRegs(op1);
2389
2390     ReturnTypeDesc* retTypeDesc = call->GetReturnTypeDesc();
2391     unsigned        regCount    = retTypeDesc->GetReturnRegCount();
2392     assert(regCount == MAX_RET_REG_COUNT);
2393
2394     // Stack store
2395     int offset = 0;
2396     for (unsigned i = 0; i < regCount; ++i)
2397     {
2398         var_types type = retTypeDesc->GetReturnRegType(i);
2399         regNumber reg  = call->GetRegNumByIdx(i);
2400         if (op1->IsCopyOrReload())
2401         {
2402             // GT_COPY/GT_RELOAD will have valid reg for those positions
2403             // that need to be copied or reloaded.
2404             regNumber reloadReg = op1->AsCopyOrReload()->GetRegNumByIdx(i);
2405             if (reloadReg != REG_NA)
2406             {
2407                 reg = reloadReg;
2408             }
2409         }
2410
2411         assert(reg != REG_NA);
2412         getEmitter()->emitIns_S_R(ins_Store(type), emitTypeSize(type), reg, lclNum, offset);
2413         offset += genTypeSize(type);
2414     }
2415
2416     varDsc->lvRegNum            = REG_STK;
2417 #else  // !FEATURE_UNIX_AMD64_STRUCT_PASSING && !_TARGET_X86_
2418     assert(!"Unreached");
2419 #endif // !FEATURE_UNIX_AMD64_STRUCT_PASSING && !_TARGET_X86_
2420 }
2421
2422 //------------------------------------------------------------------------
2423 // genLclHeap: Generate code for localloc.
2424 //
2425 // Arguments:
2426 //      tree - the localloc tree to generate.
2427 //
2428 // Notes:
2429 //      Note that for x86, we don't track ESP movements while generating the localloc code.
2430 //      The ESP tracking is used to report stack pointer-relative GC info, which is not
2431 //      interesting while doing the localloc construction. Also, for functions with localloc,
2432 //      we have EBP frames, and EBP-relative locals, and ESP-relative accesses only for function
2433 //      call arguments. We store the ESP after the localloc is complete in the LocAllocSP
2434 //      variable. This variable is implicitly reported to the VM in the GC info (its position
2435 //      is defined by convention relative to other items), and is used by the GC to find the
2436 //      "base" stack pointer in functions with localloc.
2437 //
2438 void CodeGen::genLclHeap(GenTreePtr tree)
2439 {
2440     assert(tree->OperGet() == GT_LCLHEAP);
2441     assert(compiler->compLocallocUsed);
2442
2443     GenTreePtr size = tree->gtOp.gtOp1;
2444     noway_assert((genActualType(size->gtType) == TYP_INT) || (genActualType(size->gtType) == TYP_I_IMPL));
2445
2446     regNumber   targetReg = tree->gtRegNum;
2447     regNumber   regCnt    = REG_NA;
2448     var_types   type      = genActualType(size->gtType);
2449     emitAttr    easz      = emitTypeSize(type);
2450     BasicBlock* endLabel  = nullptr;
2451
2452 #ifdef DEBUG
2453     // Verify ESP
2454     if (compiler->opts.compStackCheckOnRet)
2455     {
2456         noway_assert(compiler->lvaReturnEspCheck != 0xCCCCCCCC &&
2457                      compiler->lvaTable[compiler->lvaReturnEspCheck].lvDoNotEnregister &&
2458                      compiler->lvaTable[compiler->lvaReturnEspCheck].lvOnFrame);
2459         getEmitter()->emitIns_S_R(INS_cmp, EA_PTRSIZE, REG_SPBASE, compiler->lvaReturnEspCheck, 0);
2460
2461         BasicBlock*  esp_check = genCreateTempLabel();
2462         emitJumpKind jmpEqual  = genJumpKindForOper(GT_EQ, CK_SIGNED);
2463         inst_JMP(jmpEqual, esp_check);
2464         getEmitter()->emitIns(INS_BREAKPOINT);
2465         genDefineTempLabel(esp_check);
2466     }
2467 #endif
2468
2469     noway_assert(isFramePointerUsed()); // localloc requires Frame Pointer to be established since SP changes
2470     noway_assert(genStackLevel == 0);   // Can't have anything on the stack
2471
2472     unsigned    stackAdjustment = 0;
2473     BasicBlock* loop            = nullptr;
2474
2475     // compute the amount of memory to allocate to properly STACK_ALIGN.
2476     size_t amount = 0;
2477     if (size->IsCnsIntOrI())
2478     {
2479         // If size is a constant, then it must be contained.
2480         assert(size->isContained());
2481
2482         // If amount is zero then return null in targetReg
2483         amount = size->gtIntCon.gtIconVal;
2484         if (amount == 0)
2485         {
2486             instGen_Set_Reg_To_Zero(EA_PTRSIZE, targetReg);
2487             goto BAILOUT;
2488         }
2489
2490         // 'amount' is the total number of bytes to localloc to properly STACK_ALIGN
2491         amount = AlignUp(amount, STACK_ALIGN);
2492     }
2493     else
2494     {
2495         // The localloc requested memory size is non-constant.
2496
2497         // Put the size value in targetReg. If it is zero, bail out by returning null in targetReg.
2498         genConsumeRegAndCopy(size, targetReg);
2499         endLabel = genCreateTempLabel();
2500         getEmitter()->emitIns_R_R(INS_test, easz, targetReg, targetReg);
2501         inst_JMP(EJ_je, endLabel);
2502
2503         // Compute the size of the block to allocate and perform alignment.
2504         // If compInitMem=true, we can reuse targetReg as regcnt,
2505         // since we don't need any internal registers.
2506         if (compiler->info.compInitMem)
2507         {
2508             assert(tree->AvailableTempRegCount() == 0);
2509             regCnt = targetReg;
2510         }
2511         else
2512         {
2513             regCnt = tree->ExtractTempReg();
2514             if (regCnt != targetReg)
2515             {
2516                 // Above, we put the size in targetReg. Now, copy it to our new temp register if necessary.
2517                 inst_RV_RV(INS_mov, regCnt, targetReg, size->TypeGet());
2518             }
2519         }
2520
2521         // Round up the number of bytes to allocate to a STACK_ALIGN boundary. This is done
2522         // by code like:
2523         //      add reg, 15
2524         //      and reg, -16
2525         // However, in the initialized memory case, we need the count of STACK_ALIGN-sized
2526         // elements, not a byte count, after the alignment. So instead of the "and", which
2527         // becomes unnecessary, generate a shift, e.g.:
2528         //      add reg, 15
2529         //      shr reg, 4
2530
2531         inst_RV_IV(INS_add, regCnt, STACK_ALIGN - 1, emitActualTypeSize(type));
2532
2533         if (compiler->info.compInitMem)
2534         {
2535             // Convert the count from a count of bytes to a loop count. We will loop once per
2536             // stack alignment size, so each loop will zero 4 bytes on x86 and 16 bytes on x64.
2537             // Note that we zero a single reg-size word per iteration on x86, and 2 reg-size
2538             // words per iteration on x64. We will shift off all the stack alignment bits
2539             // added above, so there is no need for an 'and' instruction.
2540
2541             // --- shr regCnt, 2 (or 4) ---
2542             inst_RV_SH(INS_SHIFT_RIGHT_LOGICAL, EA_PTRSIZE, regCnt, STACK_ALIGN_SHIFT_ALL);
2543         }
2544         else
2545         {
2546             // Otherwise, mask off the low bits to align the byte count.
2547             inst_RV_IV(INS_AND, regCnt, ~(STACK_ALIGN - 1), emitActualTypeSize(type));
2548         }
2549     }
2550
2551 #if FEATURE_FIXED_OUT_ARGS
2552     // If we have an outgoing arg area then we must adjust the SP by popping off the
2553     // outgoing arg area. We will restore it right before we return from this method.
2554     //
2555     // Localloc returns stack space that aligned to STACK_ALIGN bytes. The following
2556     // are the cases that need to be handled:
2557     //   i) Method has out-going arg area.
2558     //      It is guaranteed that size of out-going arg area is STACK_ALIGN'ed (see fgMorphArgs).
2559     //      Therefore, we will pop off the out-going arg area from RSP before allocating the localloc space.
2560     //  ii) Method has no out-going arg area.
2561     //      Nothing to pop off from the stack.
2562     if (compiler->lvaOutgoingArgSpaceSize > 0)
2563     {
2564         assert((compiler->lvaOutgoingArgSpaceSize % STACK_ALIGN) == 0); // This must be true for the stack to remain
2565                                                                         // aligned
2566         inst_RV_IV(INS_add, REG_SPBASE, compiler->lvaOutgoingArgSpaceSize, EA_PTRSIZE);
2567         stackAdjustment += compiler->lvaOutgoingArgSpaceSize;
2568     }
2569 #endif
2570
2571     if (size->IsCnsIntOrI())
2572     {
2573         // We should reach here only for non-zero, constant size allocations.
2574         assert(amount > 0);
2575         assert((amount % STACK_ALIGN) == 0);
2576         assert((amount % REGSIZE_BYTES) == 0);
2577
2578         // For small allocations we will generate up to six push 0 inline
2579         size_t cntRegSizedWords = amount / REGSIZE_BYTES;
2580         if (cntRegSizedWords <= 6)
2581         {
2582             for (; cntRegSizedWords != 0; cntRegSizedWords--)
2583             {
2584                 inst_IV(INS_push_hide, 0); // push_hide means don't track the stack
2585             }
2586             goto ALLOC_DONE;
2587         }
2588
2589         bool doNoInitLessThanOnePageAlloc =
2590             !compiler->info.compInitMem && (amount < compiler->eeGetPageSize()); // must be < not <=
2591
2592 #ifdef _TARGET_X86_
2593         bool needRegCntRegister = true;
2594 #else  // !_TARGET_X86_
2595         bool needRegCntRegister = !doNoInitLessThanOnePageAlloc;
2596 #endif // !_TARGET_X86_
2597
2598         if (needRegCntRegister)
2599         {
2600             // If compInitMem=true, we can reuse targetReg as regcnt.
2601             // Since size is a constant, regCnt is not yet initialized.
2602             assert(regCnt == REG_NA);
2603             if (compiler->info.compInitMem)
2604             {
2605                 assert(tree->AvailableTempRegCount() == 0);
2606                 regCnt = targetReg;
2607             }
2608             else
2609             {
2610                 regCnt = tree->ExtractTempReg();
2611             }
2612         }
2613
2614         if (doNoInitLessThanOnePageAlloc)
2615         {
2616             // Since the size is less than a page, simply adjust ESP.
2617             // ESP might already be in the guard page, so we must touch it BEFORE
2618             // the alloc, not after.
2619             CLANG_FORMAT_COMMENT_ANCHOR;
2620
2621 #ifdef _TARGET_X86_
2622             // For x86, we don't want to use "sub ESP" because we don't want the emitter to track the adjustment
2623             // to ESP. So do the work in the count register.
2624             // TODO-CQ: manipulate ESP directly, to share code, reduce #ifdefs, and improve CQ. This would require
2625             // creating a way to temporarily turn off the emitter's tracking of ESP, maybe marking instrDescs as "don't
2626             // track".
2627             inst_RV_RV(INS_mov, regCnt, REG_SPBASE, TYP_I_IMPL);
2628             getEmitter()->emitIns_AR_R(INS_TEST, EA_4BYTE, REG_SPBASE, REG_SPBASE, 0);
2629             inst_RV_IV(INS_sub, regCnt, amount, EA_PTRSIZE);
2630             inst_RV_RV(INS_mov, REG_SPBASE, regCnt, TYP_I_IMPL);
2631 #else  // !_TARGET_X86_
2632             getEmitter()->emitIns_AR_R(INS_TEST, EA_4BYTE, REG_SPBASE, REG_SPBASE, 0);
2633             inst_RV_IV(INS_sub, REG_SPBASE, amount, EA_PTRSIZE);
2634 #endif // !_TARGET_X86_
2635
2636             goto ALLOC_DONE;
2637         }
2638
2639         // else, "mov regCnt, amount"
2640
2641         if (compiler->info.compInitMem)
2642         {
2643             // When initializing memory, we want 'amount' to be the loop count.
2644             assert((amount % STACK_ALIGN) == 0);
2645             amount /= STACK_ALIGN;
2646         }
2647
2648         genSetRegToIcon(regCnt, amount, ((int)amount == amount) ? TYP_INT : TYP_LONG);
2649     }
2650
2651     loop = genCreateTempLabel();
2652     if (compiler->info.compInitMem)
2653     {
2654         // At this point 'regCnt' is set to the number of loop iterations for this loop, if each
2655         // iteration zeros (and subtracts from the stack pointer) STACK_ALIGN bytes.
2656         // Since we have to zero out the allocated memory AND ensure that RSP is always valid
2657         // by tickling the pages, we will just push 0's on the stack.
2658
2659         assert(genIsValidIntReg(regCnt));
2660
2661         // Loop:
2662         genDefineTempLabel(loop);
2663
2664         static_assert_no_msg((STACK_ALIGN % REGSIZE_BYTES) == 0);
2665         unsigned const count = (STACK_ALIGN / REGSIZE_BYTES);
2666
2667         for (unsigned i = 0; i < count; i++)
2668         {
2669             inst_IV(INS_push_hide, 0); // --- push REG_SIZE bytes of 0
2670         }
2671         // Note that the stack must always be aligned to STACK_ALIGN bytes
2672
2673         // Decrement the loop counter and loop if not done.
2674         inst_RV(INS_dec, regCnt, TYP_I_IMPL);
2675         inst_JMP(EJ_jne, loop);
2676     }
2677     else
2678     {
2679         // At this point 'regCnt' is set to the total number of bytes to localloc.
2680         //
2681         // We don't need to zero out the allocated memory. However, we do have
2682         // to tickle the pages to ensure that ESP is always valid and is
2683         // in sync with the "stack guard page".  Note that in the worst
2684         // case ESP is on the last byte of the guard page.  Thus you must
2685         // touch ESP+0 first not ESP+x01000.
2686         //
2687         // Another subtlety is that you don't want ESP to be exactly on the
2688         // boundary of the guard page because PUSH is predecrement, thus
2689         // call setup would not touch the guard page but just beyond it
2690         //
2691         // Note that we go through a few hoops so that ESP never points to
2692         // illegal pages at any time during the tickling process
2693         //
2694         //       neg   REGCNT
2695         //       add   REGCNT, ESP      // reg now holds ultimate ESP
2696         //       jb    loop             // result is smaller than orignial ESP (no wrap around)
2697         //       xor   REGCNT, REGCNT,  // Overflow, pick lowest possible number
2698         //  loop:
2699         //       test  ESP, [ESP+0]     // tickle the page
2700         //       mov   REGTMP, ESP
2701         //       sub   REGTMP, PAGE_SIZE
2702         //       mov   ESP, REGTMP
2703         //       cmp   ESP, REGCNT
2704         //       jae   loop
2705         //
2706         //       mov   ESP, REG
2707         //  end:
2708         inst_RV(INS_NEG, regCnt, TYP_I_IMPL);
2709         inst_RV_RV(INS_add, regCnt, REG_SPBASE, TYP_I_IMPL);
2710         inst_JMP(EJ_jb, loop);
2711
2712         instGen_Set_Reg_To_Zero(EA_PTRSIZE, regCnt);
2713
2714         genDefineTempLabel(loop);
2715
2716         // Tickle the decremented value, and move back to ESP,
2717         // note that it has to be done BEFORE the update of ESP since
2718         // ESP might already be on the guard page.  It is OK to leave
2719         // the final value of ESP on the guard page
2720         getEmitter()->emitIns_AR_R(INS_TEST, EA_4BYTE, REG_SPBASE, REG_SPBASE, 0);
2721
2722         // This is a harmless trick to avoid the emitter trying to track the
2723         // decrement of the ESP - we do the subtraction in another reg instead
2724         // of adjusting ESP directly.
2725         regNumber regTmp = tree->GetSingleTempReg();
2726
2727         inst_RV_RV(INS_mov, regTmp, REG_SPBASE, TYP_I_IMPL);
2728         inst_RV_IV(INS_sub, regTmp, compiler->eeGetPageSize(), EA_PTRSIZE);
2729         inst_RV_RV(INS_mov, REG_SPBASE, regTmp, TYP_I_IMPL);
2730
2731         inst_RV_RV(INS_cmp, REG_SPBASE, regCnt, TYP_I_IMPL);
2732         inst_JMP(EJ_jae, loop);
2733
2734         // Move the final value to ESP
2735         inst_RV_RV(INS_mov, REG_SPBASE, regCnt);
2736     }
2737
2738 ALLOC_DONE:
2739     // Re-adjust SP to allocate out-going arg area
2740     if (stackAdjustment > 0)
2741     {
2742         assert((stackAdjustment % STACK_ALIGN) == 0); // This must be true for the stack to remain aligned
2743         inst_RV_IV(INS_sub, REG_SPBASE, stackAdjustment, EA_PTRSIZE);
2744     }
2745
2746     // Return the stackalloc'ed address in result register.
2747     // TargetReg = RSP + stackAdjustment.
2748     getEmitter()->emitIns_R_AR(INS_lea, EA_PTRSIZE, targetReg, REG_SPBASE, stackAdjustment);
2749
2750     if (endLabel != nullptr)
2751     {
2752         genDefineTempLabel(endLabel);
2753     }
2754
2755 BAILOUT:
2756
2757     // Write the lvaLocAllocSPvar stack frame slot
2758     if (compiler->lvaLocAllocSPvar != BAD_VAR_NUM)
2759     {
2760         getEmitter()->emitIns_S_R(ins_Store(TYP_I_IMPL), EA_PTRSIZE, REG_SPBASE, compiler->lvaLocAllocSPvar, 0);
2761     }
2762
2763 #if STACK_PROBES
2764     if (compiler->opts.compNeedStackProbes)
2765     {
2766         genGenerateStackProbe();
2767     }
2768 #endif
2769
2770 #ifdef DEBUG
2771     // Update new ESP
2772     if (compiler->opts.compStackCheckOnRet)
2773     {
2774         noway_assert(compiler->lvaReturnEspCheck != 0xCCCCCCCC &&
2775                      compiler->lvaTable[compiler->lvaReturnEspCheck].lvDoNotEnregister &&
2776                      compiler->lvaTable[compiler->lvaReturnEspCheck].lvOnFrame);
2777         getEmitter()->emitIns_S_R(ins_Store(TYP_I_IMPL), EA_PTRSIZE, REG_SPBASE, compiler->lvaReturnEspCheck, 0);
2778     }
2779 #endif
2780
2781     genProduceReg(tree);
2782 }
2783
2784 void CodeGen::genCodeForStoreBlk(GenTreeBlk* storeBlkNode)
2785 {
2786 #ifdef JIT32_GCENCODER
2787     assert(!storeBlkNode->gtBlkOpGcUnsafe);
2788 #else
2789     if (storeBlkNode->gtBlkOpGcUnsafe)
2790     {
2791         getEmitter()->emitDisableGC();
2792     }
2793 #endif // JIT32_GCENCODER
2794
2795     bool isCopyBlk = storeBlkNode->OperIsCopyBlkOp();
2796
2797     switch (storeBlkNode->gtBlkOpKind)
2798     {
2799 #ifdef _TARGET_AMD64_
2800         case GenTreeBlk::BlkOpKindHelper:
2801             if (isCopyBlk)
2802             {
2803                 genCodeForCpBlk(storeBlkNode);
2804             }
2805             else
2806             {
2807                 genCodeForInitBlk(storeBlkNode);
2808             }
2809             break;
2810 #endif // _TARGET_AMD64_
2811         case GenTreeBlk::BlkOpKindRepInstr:
2812             if (isCopyBlk)
2813             {
2814                 genCodeForCpBlkRepMovs(storeBlkNode);
2815             }
2816             else
2817             {
2818                 genCodeForInitBlkRepStos(storeBlkNode);
2819             }
2820             break;
2821         case GenTreeBlk::BlkOpKindUnroll:
2822             if (isCopyBlk)
2823             {
2824                 genCodeForCpBlkUnroll(storeBlkNode);
2825             }
2826             else
2827             {
2828                 genCodeForInitBlkUnroll(storeBlkNode);
2829             }
2830             break;
2831         default:
2832             unreached();
2833     }
2834
2835 #ifndef JIT32_GCENCODER
2836     if (storeBlkNode->gtBlkOpGcUnsafe)
2837     {
2838         getEmitter()->emitEnableGC();
2839     }
2840 #endif // !defined(JIT32_GCENCODER)
2841 }
2842
2843 //
2844 //------------------------------------------------------------------------
2845 // genCodeForInitBlkRepStos: Generate code for InitBlk using rep stos.
2846 //
2847 // Arguments:
2848 //    initBlkNode - The Block store for which we are generating code.
2849 //
2850 // Preconditions:
2851 //    On x64:
2852 //      The size of the buffers must be a constant and also less than INITBLK_STOS_LIMIT bytes.
2853 //      Any value larger than that, we'll use the helper even if both the fill byte and the
2854 //      size are integer constants.
2855 //  On x86:
2856 //      The size must either be a non-constant or less than INITBLK_STOS_LIMIT bytes.
2857 //
2858 void CodeGen::genCodeForInitBlkRepStos(GenTreeBlk* initBlkNode)
2859 {
2860     // Make sure we got the arguments of the initblk/initobj operation in the right registers.
2861     unsigned   size    = initBlkNode->Size();
2862     GenTreePtr dstAddr = initBlkNode->Addr();
2863     GenTreePtr initVal = initBlkNode->Data();
2864     if (initVal->OperIsInitVal())
2865     {
2866         initVal = initVal->gtGetOp1();
2867     }
2868
2869 #ifdef DEBUG
2870     assert(dstAddr->isUsedFromReg());
2871     assert(initVal->isUsedFromReg());
2872 #ifdef _TARGET_AMD64_
2873     assert(size != 0);
2874 #endif
2875     if (initVal->IsCnsIntOrI())
2876     {
2877 #ifdef _TARGET_AMD64_
2878         assert(size > CPBLK_UNROLL_LIMIT && size < CPBLK_MOVS_LIMIT);
2879 #else
2880         // Note that a size of zero means a non-constant size.
2881         assert((size == 0) || (size > CPBLK_UNROLL_LIMIT));
2882 #endif
2883     }
2884
2885 #endif // DEBUG
2886
2887     genConsumeBlockOp(initBlkNode, REG_RDI, REG_RAX, REG_RCX);
2888     instGen(INS_r_stosb);
2889 }
2890
2891 // Generate code for InitBlk by performing a loop unroll
2892 // Preconditions:
2893 //   a) Both the size and fill byte value are integer constants.
2894 //   b) The size of the struct to initialize is smaller than INITBLK_UNROLL_LIMIT bytes.
2895 //
2896 void CodeGen::genCodeForInitBlkUnroll(GenTreeBlk* initBlkNode)
2897 {
2898     // Make sure we got the arguments of the initblk/initobj operation in the right registers
2899     unsigned   size    = initBlkNode->Size();
2900     GenTreePtr dstAddr = initBlkNode->Addr();
2901     GenTreePtr initVal = initBlkNode->Data();
2902     if (initVal->OperIsInitVal())
2903     {
2904         initVal = initVal->gtGetOp1();
2905     }
2906
2907     assert(dstAddr->isUsedFromReg());
2908     assert(initVal->isUsedFromReg() || (initVal->IsIntegralConst(0) && ((size & 0xf) == 0)));
2909     assert(size != 0);
2910     assert(size <= INITBLK_UNROLL_LIMIT);
2911     assert(initVal->gtSkipReloadOrCopy()->IsCnsIntOrI());
2912
2913     emitter* emit = getEmitter();
2914
2915     genConsumeOperands(initBlkNode);
2916
2917     // If the initVal was moved, or spilled and reloaded to a different register,
2918     // get the original initVal from below the GT_RELOAD, but only after capturing the valReg,
2919     // which needs to be the new register.
2920     regNumber valReg = initVal->gtRegNum;
2921     initVal          = initVal->gtSkipReloadOrCopy();
2922
2923     unsigned offset = 0;
2924
2925     // Perform an unroll using SSE2 loads and stores.
2926     if (size >= XMM_REGSIZE_BYTES)
2927     {
2928         regNumber tmpReg = initBlkNode->GetSingleTempReg();
2929         assert(genIsValidFloatReg(tmpReg));
2930
2931         if (initVal->gtIntCon.gtIconVal != 0)
2932         {
2933             emit->emitIns_R_R(INS_mov_i2xmm, EA_PTRSIZE, tmpReg, valReg);
2934             emit->emitIns_R_R(INS_punpckldq, EA_8BYTE, tmpReg, tmpReg);
2935 #ifdef _TARGET_X86_
2936             // For x86, we need one more to convert it from 8 bytes to 16 bytes.
2937             emit->emitIns_R_R(INS_punpckldq, EA_8BYTE, tmpReg, tmpReg);
2938 #endif // _TARGET_X86_
2939         }
2940         else
2941         {
2942             emit->emitIns_R_R(INS_xorpd, EA_8BYTE, tmpReg, tmpReg);
2943         }
2944
2945         // Determine how many 16 byte slots we're going to fill using SSE movs.
2946         size_t slots = size / XMM_REGSIZE_BYTES;
2947
2948         while (slots-- > 0)
2949         {
2950             emit->emitIns_AR_R(INS_movdqu, EA_8BYTE, tmpReg, dstAddr->gtRegNum, offset);
2951             offset += XMM_REGSIZE_BYTES;
2952         }
2953     }
2954
2955     // Fill the remainder (or a < 16 byte sized struct)
2956     if ((size & 8) != 0)
2957     {
2958 #ifdef _TARGET_X86_
2959         // TODO-X86-CQ: [1091735] Revisit block ops codegen. One example: use movq for 8 byte movs.
2960         emit->emitIns_AR_R(INS_mov, EA_4BYTE, valReg, dstAddr->gtRegNum, offset);
2961         offset += 4;
2962         emit->emitIns_AR_R(INS_mov, EA_4BYTE, valReg, dstAddr->gtRegNum, offset);
2963         offset += 4;
2964 #else // !_TARGET_X86_
2965
2966         emit->emitIns_AR_R(INS_mov, EA_8BYTE, valReg, dstAddr->gtRegNum, offset);
2967         offset += 8;
2968
2969 #endif // !_TARGET_X86_
2970     }
2971     if ((size & 4) != 0)
2972     {
2973         emit->emitIns_AR_R(INS_mov, EA_4BYTE, valReg, dstAddr->gtRegNum, offset);
2974         offset += 4;
2975     }
2976     if ((size & 2) != 0)
2977     {
2978         emit->emitIns_AR_R(INS_mov, EA_2BYTE, valReg, dstAddr->gtRegNum, offset);
2979         offset += 2;
2980     }
2981     if ((size & 1) != 0)
2982     {
2983         emit->emitIns_AR_R(INS_mov, EA_1BYTE, valReg, dstAddr->gtRegNum, offset);
2984     }
2985 }
2986
2987 // Generates code for InitBlk by calling the VM memset helper function.
2988 // Preconditions:
2989 // a) The size argument of the InitBlk is not an integer constant.
2990 // b) The size argument of the InitBlk is >= INITBLK_STOS_LIMIT bytes.
2991 void CodeGen::genCodeForInitBlk(GenTreeBlk* initBlkNode)
2992 {
2993 #ifdef _TARGET_AMD64_
2994     // Make sure we got the arguments of the initblk operation in the right registers
2995     unsigned   blockSize = initBlkNode->Size();
2996     GenTreePtr dstAddr   = initBlkNode->Addr();
2997     GenTreePtr initVal   = initBlkNode->Data();
2998     if (initVal->OperIsInitVal())
2999     {
3000         initVal = initVal->gtGetOp1();
3001     }
3002
3003     assert(dstAddr->isUsedFromReg());
3004     assert(initVal->isUsedFromReg());
3005
3006     if (blockSize != 0)
3007     {
3008         assert(blockSize >= CPBLK_MOVS_LIMIT);
3009     }
3010
3011     genConsumeBlockOp(initBlkNode, REG_ARG_0, REG_ARG_1, REG_ARG_2);
3012
3013     genEmitHelperCall(CORINFO_HELP_MEMSET, 0, EA_UNKNOWN);
3014 #else  // !_TARGET_AMD64_
3015     NYI_X86("Helper call for InitBlk");
3016 #endif // !_TARGET_AMD64_
3017 }
3018
3019 // Generate code for a load from some address + offset
3020 //   baseNode: tree node which can be either a local address or arbitrary node
3021 //   offset: distance from the baseNode from which to load
3022 void CodeGen::genCodeForLoadOffset(instruction ins, emitAttr size, regNumber dst, GenTree* baseNode, unsigned offset)
3023 {
3024     emitter* emit = getEmitter();
3025
3026     if (baseNode->OperIsLocalAddr())
3027     {
3028         if (baseNode->gtOper == GT_LCL_FLD_ADDR)
3029         {
3030             offset += baseNode->gtLclFld.gtLclOffs;
3031         }
3032         emit->emitIns_R_S(ins, size, dst, baseNode->gtLclVarCommon.gtLclNum, offset);
3033     }
3034     else
3035     {
3036         emit->emitIns_R_AR(ins, size, dst, baseNode->gtRegNum, offset);
3037     }
3038 }
3039
3040 //------------------------------------------------------------------------
3041 // genCodeForStoreOffset: Generate code to store a reg to [base + offset].
3042 //
3043 // Arguments:
3044 //      ins         - the instruction to generate.
3045 //      size        - the size that needs to be stored.
3046 //      src         - the register which needs to be stored.
3047 //      baseNode    - the base, relative to which to store the src register.
3048 //      offset      - the offset that is added to the baseNode to calculate the address to store into.
3049 //
3050 void CodeGen::genCodeForStoreOffset(instruction ins, emitAttr size, regNumber src, GenTree* baseNode, unsigned offset)
3051 {
3052     emitter* emit = getEmitter();
3053
3054     if (baseNode->OperIsLocalAddr())
3055     {
3056         if (baseNode->gtOper == GT_LCL_FLD_ADDR)
3057         {
3058             offset += baseNode->gtLclFld.gtLclOffs;
3059         }
3060
3061         emit->emitIns_S_R(ins, size, src, baseNode->AsLclVarCommon()->GetLclNum(), offset);
3062     }
3063     else
3064     {
3065         emit->emitIns_AR_R(ins, size, src, baseNode->gtRegNum, offset);
3066     }
3067 }
3068
3069 // Generates CpBlk code by performing a loop unroll
3070 // Preconditions:
3071 //  The size argument of the CpBlk node is a constant and <= 64 bytes.
3072 //  This may seem small but covers >95% of the cases in several framework assemblies.
3073 //
3074 void CodeGen::genCodeForCpBlkUnroll(GenTreeBlk* cpBlkNode)
3075 {
3076     // Make sure we got the arguments of the cpblk operation in the right registers
3077     unsigned   size    = cpBlkNode->Size();
3078     GenTreePtr dstAddr = cpBlkNode->Addr();
3079     GenTreePtr source  = cpBlkNode->Data();
3080     GenTreePtr srcAddr = nullptr;
3081     assert(size <= CPBLK_UNROLL_LIMIT);
3082
3083     emitter* emit = getEmitter();
3084
3085     if (source->gtOper == GT_IND)
3086     {
3087         srcAddr = source->gtGetOp1();
3088         if (srcAddr->isUsedFromReg())
3089         {
3090             genConsumeReg(srcAddr);
3091         }
3092     }
3093     else
3094     {
3095         noway_assert(source->IsLocal());
3096         // TODO-Cleanup: Consider making the addrForm() method in Rationalize public, e.g. in GenTree.
3097         // OR: transform source to GT_IND(GT_LCL_VAR_ADDR)
3098         if (source->OperGet() == GT_LCL_VAR)
3099         {
3100             source->SetOper(GT_LCL_VAR_ADDR);
3101         }
3102         else
3103         {
3104             assert(source->OperGet() == GT_LCL_FLD);
3105             source->SetOper(GT_LCL_FLD_ADDR);
3106         }
3107         srcAddr = source;
3108     }
3109
3110     if (dstAddr->isUsedFromReg())
3111     {
3112         genConsumeReg(dstAddr);
3113     }
3114
3115     unsigned offset = 0;
3116
3117     // If the size of this struct is larger than 16 bytes
3118     // let's use SSE2 to be able to do 16 byte at a time
3119     // loads and stores.
3120
3121     if (size >= XMM_REGSIZE_BYTES)
3122     {
3123         regNumber xmmReg = cpBlkNode->GetSingleTempReg(RBM_ALLFLOAT);
3124         assert(genIsValidFloatReg(xmmReg));
3125         size_t slots = size / XMM_REGSIZE_BYTES;
3126
3127         // TODO: In the below code the load and store instructions are for 16 bytes, but the
3128         //       type is EA_8BYTE. The movdqa/u are 16 byte instructions, so it works, but
3129         //       this probably needs to be changed.
3130         while (slots-- > 0)
3131         {
3132             // Load
3133             genCodeForLoadOffset(INS_movdqu, EA_8BYTE, xmmReg, srcAddr, offset);
3134             // Store
3135             genCodeForStoreOffset(INS_movdqu, EA_8BYTE, xmmReg, dstAddr, offset);
3136             offset += XMM_REGSIZE_BYTES;
3137         }
3138     }
3139
3140     // Fill the remainder (15 bytes or less) if there's one.
3141     if ((size & 0xf) != 0)
3142     {
3143         // Grab the integer temp register to emit the remaining loads and stores.
3144         regNumber tmpReg = cpBlkNode->GetSingleTempReg(RBM_ALLINT);
3145
3146         if ((size & 8) != 0)
3147         {
3148 #ifdef _TARGET_X86_
3149             // TODO-X86-CQ: [1091735] Revisit block ops codegen. One example: use movq for 8 byte movs.
3150             for (unsigned savedOffs = offset; offset < savedOffs + 8; offset += 4)
3151             {
3152                 genCodeForLoadOffset(INS_mov, EA_4BYTE, tmpReg, srcAddr, offset);
3153                 genCodeForStoreOffset(INS_mov, EA_4BYTE, tmpReg, dstAddr, offset);
3154             }
3155 #else  // !_TARGET_X86_
3156             genCodeForLoadOffset(INS_mov, EA_8BYTE, tmpReg, srcAddr, offset);
3157             genCodeForStoreOffset(INS_mov, EA_8BYTE, tmpReg, dstAddr, offset);
3158             offset += 8;
3159 #endif // !_TARGET_X86_
3160         }
3161         if ((size & 4) != 0)
3162         {
3163             genCodeForLoadOffset(INS_mov, EA_4BYTE, tmpReg, srcAddr, offset);
3164             genCodeForStoreOffset(INS_mov, EA_4BYTE, tmpReg, dstAddr, offset);
3165             offset += 4;
3166         }
3167         if ((size & 2) != 0)
3168         {
3169             genCodeForLoadOffset(INS_mov, EA_2BYTE, tmpReg, srcAddr, offset);
3170             genCodeForStoreOffset(INS_mov, EA_2BYTE, tmpReg, dstAddr, offset);
3171             offset += 2;
3172         }
3173         if ((size & 1) != 0)
3174         {
3175             genCodeForLoadOffset(INS_mov, EA_1BYTE, tmpReg, srcAddr, offset);
3176             genCodeForStoreOffset(INS_mov, EA_1BYTE, tmpReg, dstAddr, offset);
3177         }
3178     }
3179 }
3180
3181 // Generate code for CpBlk by using rep movs
3182 // Preconditions:
3183 // The size argument of the CpBlk is a constant and is between
3184 // CPBLK_UNROLL_LIMIT and CPBLK_MOVS_LIMIT bytes.
3185 void CodeGen::genCodeForCpBlkRepMovs(GenTreeBlk* cpBlkNode)
3186 {
3187     // Make sure we got the arguments of the cpblk operation in the right registers
3188     unsigned   size    = cpBlkNode->Size();
3189     GenTreePtr dstAddr = cpBlkNode->Addr();
3190     GenTreePtr source  = cpBlkNode->Data();
3191     GenTreePtr srcAddr = nullptr;
3192
3193 #ifdef DEBUG
3194     assert(dstAddr->isUsedFromReg());
3195     assert(source->isContained());
3196
3197 #ifdef _TARGET_X86_
3198     if (size == 0)
3199     {
3200         noway_assert(cpBlkNode->OperGet() == GT_STORE_DYN_BLK);
3201     }
3202     else
3203 #endif
3204     {
3205 #ifdef _TARGET_X64_
3206         assert(size > CPBLK_UNROLL_LIMIT && size < CPBLK_MOVS_LIMIT);
3207 #else
3208         assert(size > CPBLK_UNROLL_LIMIT);
3209 #endif
3210     }
3211 #endif // DEBUG
3212
3213     genConsumeBlockOp(cpBlkNode, REG_RDI, REG_RSI, REG_RCX);
3214     instGen(INS_r_movsb);
3215 }
3216
3217 #ifdef FEATURE_PUT_STRUCT_ARG_STK
3218 //------------------------------------------------------------------------
3219 // CodeGen::genMove8IfNeeded: Conditionally move 8 bytes of a struct to the argument area
3220 //
3221 // Arguments:
3222 //    size       - The size of bytes remaining to be moved
3223 //    longTmpReg - The tmp register to be used for the long value
3224 //    srcAddr    - The address of the source struct
3225 //    offset     - The current offset being copied
3226 //
3227 // Return Value:
3228 //    Returns the number of bytes moved (8 or 0).
3229 //
3230 // Notes:
3231 //    This is used in the PutArgStkKindUnroll case, to move any bytes that are
3232 //    not an even multiple of 16.
3233 //    On x86, longTmpReg must be an xmm reg; on x64 it must be an integer register.
3234 //    This is checked by genStoreRegToStackArg.
3235 //
3236 unsigned CodeGen::genMove8IfNeeded(unsigned size, regNumber longTmpReg, GenTree* srcAddr, unsigned offset)
3237 {
3238 #ifdef _TARGET_X86_
3239     instruction longMovIns = INS_movq;
3240 #else  // !_TARGET_X86_
3241     instruction longMovIns = INS_mov;
3242 #endif // !_TARGET_X86_
3243     if ((size & 8) != 0)
3244     {
3245         genCodeForLoadOffset(longMovIns, EA_8BYTE, longTmpReg, srcAddr, offset);
3246         genStoreRegToStackArg(TYP_LONG, longTmpReg, offset);
3247         return 8;
3248     }
3249     return 0;
3250 }
3251
3252 //------------------------------------------------------------------------
3253 // CodeGen::genMove4IfNeeded: Conditionally move 4 bytes of a struct to the argument area
3254 //
3255 // Arguments:
3256 //    size      - The size of bytes remaining to be moved
3257 //    intTmpReg - The tmp register to be used for the long value
3258 //    srcAddr   - The address of the source struct
3259 //    offset    - The current offset being copied
3260 //
3261 // Return Value:
3262 //    Returns the number of bytes moved (4 or 0).
3263 //
3264 // Notes:
3265 //    This is used in the PutArgStkKindUnroll case, to move any bytes that are
3266 //    not an even multiple of 16.
3267 //    intTmpReg must be an integer register.
3268 //    This is checked by genStoreRegToStackArg.
3269 //
3270 unsigned CodeGen::genMove4IfNeeded(unsigned size, regNumber intTmpReg, GenTree* srcAddr, unsigned offset)
3271 {
3272     if ((size & 4) != 0)
3273     {
3274         genCodeForLoadOffset(INS_mov, EA_4BYTE, intTmpReg, srcAddr, offset);
3275         genStoreRegToStackArg(TYP_INT, intTmpReg, offset);
3276         return 4;
3277     }
3278     return 0;
3279 }
3280
3281 //------------------------------------------------------------------------
3282 // CodeGen::genMove2IfNeeded: Conditionally move 2 bytes of a struct to the argument area
3283 //
3284 // Arguments:
3285 //    size      - The size of bytes remaining to be moved
3286 //    intTmpReg - The tmp register to be used for the long value
3287 //    srcAddr   - The address of the source struct
3288 //    offset    - The current offset being copied
3289 //
3290 // Return Value:
3291 //    Returns the number of bytes moved (2 or 0).
3292 //
3293 // Notes:
3294 //    This is used in the PutArgStkKindUnroll case, to move any bytes that are
3295 //    not an even multiple of 16.
3296 //    intTmpReg must be an integer register.
3297 //    This is checked by genStoreRegToStackArg.
3298 //
3299 unsigned CodeGen::genMove2IfNeeded(unsigned size, regNumber intTmpReg, GenTree* srcAddr, unsigned offset)
3300 {
3301     if ((size & 2) != 0)
3302     {
3303         genCodeForLoadOffset(INS_mov, EA_2BYTE, intTmpReg, srcAddr, offset);
3304         genStoreRegToStackArg(TYP_SHORT, intTmpReg, offset);
3305         return 2;
3306     }
3307     return 0;
3308 }
3309
3310 //------------------------------------------------------------------------
3311 // CodeGen::genMove1IfNeeded: Conditionally move 1 byte of a struct to the argument area
3312 //
3313 // Arguments:
3314 //    size      - The size of bytes remaining to be moved
3315 //    intTmpReg - The tmp register to be used for the long value
3316 //    srcAddr   - The address of the source struct
3317 //    offset    - The current offset being copied
3318 //
3319 // Return Value:
3320 //    Returns the number of bytes moved (1 or 0).
3321 //
3322 // Notes:
3323 //    This is used in the PutArgStkKindUnroll case, to move any bytes that are
3324 //    not an even multiple of 16.
3325 //    intTmpReg must be an integer register.
3326 //    This is checked by genStoreRegToStackArg.
3327 //
3328 unsigned CodeGen::genMove1IfNeeded(unsigned size, regNumber intTmpReg, GenTree* srcAddr, unsigned offset)
3329 {
3330
3331     if ((size & 1) != 0)
3332     {
3333         genCodeForLoadOffset(INS_mov, EA_1BYTE, intTmpReg, srcAddr, offset);
3334         genStoreRegToStackArg(TYP_BYTE, intTmpReg, offset);
3335         return 1;
3336     }
3337     return 0;
3338 }
3339
3340 //---------------------------------------------------------------------------------------------------------------//
3341 // genStructPutArgUnroll: Generates code for passing a struct arg on stack by value using loop unrolling.
3342 //
3343 // Arguments:
3344 //     putArgNode  - the PutArgStk tree.
3345 //
3346 // Notes:
3347 //     m_stkArgVarNum must be set to the base var number, relative to which the by-val struct will be copied to the
3348 //     stack.
3349 //
3350 // TODO-Amd64-Unix: Try to share code with copyblk.
3351 //      Need refactoring of copyblk before it could be used for putarg_stk.
3352 //      The difference for now is that a putarg_stk contains its children, while cpyblk does not.
3353 //      This creates differences in code. After some significant refactoring it could be reused.
3354 //
3355 void CodeGen::genStructPutArgUnroll(GenTreePutArgStk* putArgNode)
3356 {
3357     // We will never call this method for SIMD types, which are stored directly
3358     // in genPutStructArgStk().
3359     noway_assert(putArgNode->TypeGet() == TYP_STRUCT);
3360
3361     // Make sure we got the arguments of the cpblk operation in the right registers
3362     GenTreePtr dstAddr = putArgNode;
3363     GenTreePtr src     = putArgNode->gtOp.gtOp1;
3364
3365     unsigned size = putArgNode->getArgSize();
3366     assert(size <= CPBLK_UNROLL_LIMIT);
3367
3368     emitter* emit         = getEmitter();
3369     unsigned putArgOffset = putArgNode->getArgOffset();
3370
3371     assert(src->isContained());
3372
3373     assert(src->gtOper == GT_OBJ);
3374
3375     if (src->gtOp.gtOp1->isUsedFromReg())
3376     {
3377         genConsumeReg(src->gtOp.gtOp1);
3378     }
3379
3380     unsigned offset = 0;
3381
3382     regNumber xmmTmpReg  = REG_NA;
3383     regNumber intTmpReg  = REG_NA;
3384     regNumber longTmpReg = REG_NA;
3385 #ifdef _TARGET_X86_
3386     // On x86 we use an XMM register for both 16 and 8-byte chunks, but if it's
3387     // less than 16 bytes, we will just be using pushes
3388     if (size >= 8)
3389     {
3390         xmmTmpReg  = putArgNode->GetSingleTempReg(RBM_ALLFLOAT);
3391         longTmpReg = xmmTmpReg;
3392     }
3393     if ((size & 0x7) != 0)
3394     {
3395         intTmpReg = putArgNode->GetSingleTempReg(RBM_ALLINT);
3396     }
3397 #else  // !_TARGET_X86_
3398     // On x64 we use an XMM register only for 16-byte chunks.
3399     if (size >= XMM_REGSIZE_BYTES)
3400     {
3401         xmmTmpReg = putArgNode->GetSingleTempReg(RBM_ALLFLOAT);
3402     }
3403     if ((size & 0xf) != 0)
3404     {
3405         intTmpReg  = putArgNode->GetSingleTempReg(RBM_ALLINT);
3406         longTmpReg = intTmpReg;
3407     }
3408 #endif // !_TARGET_X86_
3409
3410     // If the size of this struct is larger than 16 bytes
3411     // let's use SSE2 to be able to do 16 byte at a time
3412     // loads and stores.
3413     if (size >= XMM_REGSIZE_BYTES)
3414     {
3415 #ifdef _TARGET_X86_
3416         assert(!m_pushStkArg);
3417 #endif // _TARGET_X86_
3418         size_t slots = size / XMM_REGSIZE_BYTES;
3419
3420         assert(putArgNode->gtGetOp1()->isContained());
3421         assert(putArgNode->gtGetOp1()->gtOp.gtOper == GT_OBJ);
3422
3423         // TODO: In the below code the load and store instructions are for 16 bytes, but the
3424         //          type is EA_8BYTE. The movdqa/u are 16 byte instructions, so it works, but
3425         //          this probably needs to be changed.
3426         while (slots-- > 0)
3427         {
3428             // Load
3429             genCodeForLoadOffset(INS_movdqu, EA_8BYTE, xmmTmpReg, src->gtGetOp1(), offset);
3430
3431             // Store
3432             genStoreRegToStackArg(TYP_STRUCT, xmmTmpReg, offset);
3433
3434             offset += XMM_REGSIZE_BYTES;
3435         }
3436     }
3437
3438     // Fill the remainder (15 bytes or less) if there's one.
3439     if ((size & 0xf) != 0)
3440     {
3441 #ifdef _TARGET_X86_
3442         if (m_pushStkArg)
3443         {
3444             // This case is currently supported only for the case where the total size is
3445             // less than XMM_REGSIZE_BYTES. We need to push the remaining chunks in reverse
3446             // order. However, morph has ensured that we have a struct that is an even
3447             // multiple of TARGET_POINTER_SIZE, so we don't need to worry about alignment.
3448             assert(((size & 0xc) == size) && (offset == 0));
3449             // If we have a 4 byte chunk, load it from either offset 0 or 8, depending on
3450             // whether we've got an 8 byte chunk, and then push it on the stack.
3451             unsigned pushedBytes = genMove4IfNeeded(size, intTmpReg, src->gtOp.gtOp1, size & 0x8);
3452             // Now if we have an 8 byte chunk, load it from offset 0 (it's the first chunk)
3453             // and push it on the stack.
3454             pushedBytes += genMove8IfNeeded(size, longTmpReg, src->gtOp.gtOp1, 0);
3455         }
3456         else
3457 #endif // _TARGET_X86_
3458         {
3459             offset += genMove8IfNeeded(size, longTmpReg, src->gtOp.gtOp1, offset);
3460             offset += genMove4IfNeeded(size, intTmpReg, src->gtOp.gtOp1, offset);
3461             offset += genMove2IfNeeded(size, intTmpReg, src->gtOp.gtOp1, offset);
3462             offset += genMove1IfNeeded(size, intTmpReg, src->gtOp.gtOp1, offset);
3463             assert(offset == size);
3464         }
3465     }
3466 }
3467
3468 //------------------------------------------------------------------------
3469 // genStructPutArgRepMovs: Generates code for passing a struct arg by value on stack using Rep Movs.
3470 //
3471 // Arguments:
3472 //     putArgNode  - the PutArgStk tree.
3473 //
3474 // Preconditions:
3475 //     The size argument of the PutArgStk (for structs) is a constant and is between
3476 //     CPBLK_UNROLL_LIMIT and CPBLK_MOVS_LIMIT bytes.
3477 //     m_stkArgVarNum must be set to the base var number, relative to which the by-val struct bits will go.
3478 //
3479 void CodeGen::genStructPutArgRepMovs(GenTreePutArgStk* putArgNode)
3480 {
3481     assert(putArgNode->TypeGet() == TYP_STRUCT);
3482     assert(putArgNode->getArgSize() > CPBLK_UNROLL_LIMIT);
3483
3484     // Make sure we got the arguments of the cpblk operation in the right registers
3485     GenTreePtr dstAddr = putArgNode;
3486     GenTreePtr srcAddr = putArgNode->gtGetOp1();
3487
3488     // Validate state.
3489     assert(putArgNode->gtRsvdRegs == (RBM_RDI | RBM_RCX | RBM_RSI));
3490     assert(srcAddr->isContained());
3491
3492     genConsumePutStructArgStk(putArgNode, REG_RDI, REG_RSI, REG_RCX);
3493     instGen(INS_r_movsb);
3494 }
3495
3496 //------------------------------------------------------------------------
3497 // If any Vector3 args are on stack and they are not pass-by-ref, the upper 32bits
3498 // must be cleared to zeroes. The native compiler doesn't clear the upper bits
3499 // and there is no way to know if the caller is native or not. So, the upper
3500 // 32 bits of Vector argument on stack are always cleared to zero.
3501 #if defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) && defined(FEATURE_SIMD)
3502 void CodeGen::genClearStackVec3ArgUpperBits()
3503 {
3504 #ifdef DEBUG
3505     if (verbose)
3506     {
3507         printf("*************** In genClearStackVec3ArgUpperBits()\n");
3508     }
3509 #endif
3510
3511     assert(compiler->compGeneratingProlog);
3512
3513     unsigned varNum = 0;
3514
3515     for (unsigned varNum = 0; varNum < compiler->info.compArgsCount; varNum++)
3516     {
3517         LclVarDsc* varDsc = &(compiler->lvaTable[varNum]);
3518         assert(varDsc->lvIsParam);
3519
3520         // Does var has simd12 type?
3521         if (varDsc->lvType != TYP_SIMD12)
3522         {
3523             continue;
3524         }
3525
3526         if (!varDsc->lvIsRegArg)
3527         {
3528             // Clear the upper 32 bits by mov dword ptr [V_ARG_BASE+0xC], 0
3529             getEmitter()->emitIns_S_I(ins_Store(TYP_INT), EA_4BYTE, varNum, genTypeSize(TYP_FLOAT) * 3, 0);
3530         }
3531         else
3532         {
3533             // Assume that for x64 linux, an argument is fully in registers
3534             // or fully on stack.
3535             regNumber argReg = varDsc->GetOtherArgReg();
3536
3537             // Clear the upper 32 bits by two shift instructions.
3538             // argReg = argReg << 96
3539             getEmitter()->emitIns_R_I(INS_pslldq, emitActualTypeSize(TYP_SIMD12), argReg, 12);
3540             // argReg = argReg >> 96
3541             getEmitter()->emitIns_R_I(INS_psrldq, emitActualTypeSize(TYP_SIMD12), argReg, 12);
3542         }
3543     }
3544 }
3545 #endif // defined(FEATURE_UNIX_AMD64_STRUCT_PASSING) && defined(FEATURE_SIMD)
3546 #endif // FEATURE_PUT_STRUCT_ARG_STK
3547
3548 // Generate code for CpObj nodes wich copy structs that have interleaved
3549 // GC pointers.
3550 // This will generate a sequence of movsp instructions for the cases of non-gc members.
3551 // Note that movsp is an alias for movsd on x86 and movsq on x64.
3552 // and calls to the BY_REF_ASSIGN helper otherwise.
3553 void CodeGen::genCodeForCpObj(GenTreeObj* cpObjNode)
3554 {
3555     // Make sure we got the arguments of the cpobj operation in the right registers
3556     GenTreePtr dstAddr       = cpObjNode->Addr();
3557     GenTreePtr source        = cpObjNode->Data();
3558     GenTreePtr srcAddr       = nullptr;
3559     var_types  srcAddrType   = TYP_BYREF;
3560     bool       sourceIsLocal = false;
3561
3562     assert(source->isContained());
3563     if (source->gtOper == GT_IND)
3564     {
3565         srcAddr = source->gtGetOp1();
3566         assert(srcAddr->isUsedFromReg());
3567     }
3568     else
3569     {
3570         noway_assert(source->IsLocal());
3571         sourceIsLocal = true;
3572     }
3573
3574     bool dstOnStack = dstAddr->OperIsLocalAddr();
3575
3576 #ifdef DEBUG
3577
3578     assert(dstAddr->isUsedFromReg());
3579
3580     // If the GenTree node has data about GC pointers, this means we're dealing
3581     // with CpObj, so this requires special logic.
3582     assert(cpObjNode->gtGcPtrCount > 0);
3583
3584     // MovSp (alias for movsq on x64 and movsd on x86) instruction is used for copying non-gcref fields
3585     // and it needs src = RSI and dst = RDI.
3586     // Either these registers must not contain lclVars, or they must be dying or marked for spill.
3587     // This is because these registers are incremented as we go through the struct.
3588     if (!sourceIsLocal)
3589     {
3590         GenTree* actualSrcAddr    = srcAddr->gtSkipReloadOrCopy();
3591         GenTree* actualDstAddr    = dstAddr->gtSkipReloadOrCopy();
3592         unsigned srcLclVarNum     = BAD_VAR_NUM;
3593         unsigned dstLclVarNum     = BAD_VAR_NUM;
3594         bool     isSrcAddrLiveOut = false;
3595         bool     isDstAddrLiveOut = false;
3596         if (genIsRegCandidateLocal(actualSrcAddr))
3597         {
3598             srcLclVarNum     = actualSrcAddr->AsLclVarCommon()->gtLclNum;
3599             isSrcAddrLiveOut = ((actualSrcAddr->gtFlags & (GTF_VAR_DEATH | GTF_SPILL)) == 0);
3600         }
3601         if (genIsRegCandidateLocal(actualDstAddr))
3602         {
3603             dstLclVarNum     = actualDstAddr->AsLclVarCommon()->gtLclNum;
3604             isDstAddrLiveOut = ((actualDstAddr->gtFlags & (GTF_VAR_DEATH | GTF_SPILL)) == 0);
3605         }
3606         assert((actualSrcAddr->gtRegNum != REG_RSI) || !isSrcAddrLiveOut ||
3607                ((srcLclVarNum == dstLclVarNum) && !isDstAddrLiveOut));
3608         assert((actualDstAddr->gtRegNum != REG_RDI) || !isDstAddrLiveOut ||
3609                ((srcLclVarNum == dstLclVarNum) && !isSrcAddrLiveOut));
3610         srcAddrType = srcAddr->TypeGet();
3611     }
3612 #endif // DEBUG
3613
3614     // Consume the operands and get them into the right registers.
3615     // They may now contain gc pointers (depending on their type; gcMarkRegPtrVal will "do the right thing").
3616     genConsumeBlockOp(cpObjNode, REG_RDI, REG_RSI, REG_NA);
3617     gcInfo.gcMarkRegPtrVal(REG_RSI, srcAddrType);
3618     gcInfo.gcMarkRegPtrVal(REG_RDI, dstAddr->TypeGet());
3619
3620     unsigned slots = cpObjNode->gtSlots;
3621
3622     // If we can prove it's on the stack we don't need to use the write barrier.
3623     if (dstOnStack)
3624     {
3625         if (slots >= CPOBJ_NONGC_SLOTS_LIMIT)
3626         {
3627             // If the destination of the CpObj is on the stack, make sure we allocated
3628             // RCX to emit the movsp (alias for movsd or movsq for 32 and 64 bits respectively).
3629             assert((cpObjNode->gtRsvdRegs & RBM_RCX) != 0);
3630
3631             getEmitter()->emitIns_R_I(INS_mov, EA_4BYTE, REG_RCX, slots);
3632             instGen(INS_r_movsp);
3633         }
3634         else
3635         {
3636             // For small structs, it's better to emit a sequence of movsp than to
3637             // emit a rep movsp instruction.
3638             while (slots > 0)
3639             {
3640                 instGen(INS_movsp);
3641                 slots--;
3642             }
3643         }
3644     }
3645     else
3646     {
3647         BYTE*    gcPtrs     = cpObjNode->gtGcPtrs;
3648         unsigned gcPtrCount = cpObjNode->gtGcPtrCount;
3649
3650         unsigned i = 0;
3651         while (i < slots)
3652         {
3653             switch (gcPtrs[i])
3654             {
3655                 case TYPE_GC_NONE:
3656                     // Let's see if we can use rep movsp instead of a sequence of movsp instructions
3657                     // to save cycles and code size.
3658                     {
3659                         unsigned nonGcSlotCount = 0;
3660
3661                         do
3662                         {
3663                             nonGcSlotCount++;
3664                             i++;
3665                         } while (i < slots && gcPtrs[i] == TYPE_GC_NONE);
3666
3667                         // If we have a very small contiguous non-gc region, it's better just to
3668                         // emit a sequence of movsp instructions
3669                         if (nonGcSlotCount < CPOBJ_NONGC_SLOTS_LIMIT)
3670                         {
3671                             while (nonGcSlotCount > 0)
3672                             {
3673                                 instGen(INS_movsp);
3674                                 nonGcSlotCount--;
3675                             }
3676                         }
3677                         else
3678                         {
3679                             // Otherwise, we can save code-size and improve CQ by emitting
3680                             // rep movsp (alias for movsd/movsq for x86/x64)
3681                             assert((cpObjNode->gtRsvdRegs & RBM_RCX) != 0);
3682
3683                             getEmitter()->emitIns_R_I(INS_mov, EA_4BYTE, REG_RCX, nonGcSlotCount);
3684                             instGen(INS_r_movsp);
3685                         }
3686                     }
3687                     break;
3688                 default:
3689                     // We have a GC pointer, call the memory barrier.
3690                     genEmitHelperCall(CORINFO_HELP_ASSIGN_BYREF, 0, EA_PTRSIZE);
3691                     gcPtrCount--;
3692                     i++;
3693             }
3694         }
3695
3696         assert(gcPtrCount == 0);
3697     }
3698
3699     // Clear the gcInfo for RSI and RDI.
3700     // While we normally update GC info prior to the last instruction that uses them,
3701     // these actually live into the helper call.
3702     gcInfo.gcMarkRegSetNpt(RBM_RSI);
3703     gcInfo.gcMarkRegSetNpt(RBM_RDI);
3704 }
3705
3706 // Generate code for a CpBlk node by the means of the VM memcpy helper call
3707 // Preconditions:
3708 // a) The size argument of the CpBlk is not an integer constant
3709 // b) The size argument is a constant but is larger than CPBLK_MOVS_LIMIT bytes.
3710 void CodeGen::genCodeForCpBlk(GenTreeBlk* cpBlkNode)
3711 {
3712 #ifdef _TARGET_AMD64_
3713     // Make sure we got the arguments of the cpblk operation in the right registers
3714     unsigned   blockSize = cpBlkNode->Size();
3715     GenTreePtr dstAddr   = cpBlkNode->Addr();
3716     GenTreePtr source    = cpBlkNode->Data();
3717     GenTreePtr srcAddr   = nullptr;
3718
3719     // Size goes in arg2
3720     if (blockSize != 0)
3721     {
3722         assert(blockSize >= CPBLK_MOVS_LIMIT);
3723         assert((cpBlkNode->gtRsvdRegs & RBM_ARG_2) != 0);
3724     }
3725     else
3726     {
3727         noway_assert(cpBlkNode->gtOper == GT_STORE_DYN_BLK);
3728     }
3729
3730     // Source address goes in arg1
3731     if (source->gtOper == GT_IND)
3732     {
3733         srcAddr = source->gtGetOp1();
3734         assert(srcAddr->isUsedFromReg());
3735     }
3736     else
3737     {
3738         noway_assert(source->IsLocal());
3739         assert((cpBlkNode->gtRsvdRegs & RBM_ARG_1) != 0);
3740         inst_RV_TT(INS_lea, REG_ARG_1, source, 0, EA_BYREF);
3741     }
3742
3743     genConsumeBlockOp(cpBlkNode, REG_ARG_0, REG_ARG_1, REG_ARG_2);
3744
3745     genEmitHelperCall(CORINFO_HELP_MEMCPY, 0, EA_UNKNOWN);
3746 #else  // !_TARGET_AMD64_
3747     noway_assert(false && "Helper call for CpBlk is not needed.");
3748 #endif // !_TARGET_AMD64_
3749 }
3750
3751 // generate code do a switch statement based on a table of ip-relative offsets
3752 void CodeGen::genTableBasedSwitch(GenTree* treeNode)
3753 {
3754     genConsumeOperands(treeNode->AsOp());
3755     regNumber idxReg  = treeNode->gtOp.gtOp1->gtRegNum;
3756     regNumber baseReg = treeNode->gtOp.gtOp2->gtRegNum;
3757
3758     regNumber tmpReg = treeNode->GetSingleTempReg();
3759
3760     // load the ip-relative offset (which is relative to start of fgFirstBB)
3761     getEmitter()->emitIns_R_ARX(INS_mov, EA_4BYTE, baseReg, baseReg, idxReg, 4, 0);
3762
3763     // add it to the absolute address of fgFirstBB
3764     compiler->fgFirstBB->bbFlags |= BBF_JMP_TARGET;
3765     getEmitter()->emitIns_R_L(INS_lea, EA_PTR_DSP_RELOC, compiler->fgFirstBB, tmpReg);
3766     getEmitter()->emitIns_R_R(INS_add, EA_PTRSIZE, baseReg, tmpReg);
3767     // jmp baseReg
3768     getEmitter()->emitIns_R(INS_i_jmp, emitTypeSize(TYP_I_IMPL), baseReg);
3769 }
3770
3771 // emits the table and an instruction to get the address of the first element
3772 void CodeGen::genJumpTable(GenTree* treeNode)
3773 {
3774     noway_assert(compiler->compCurBB->bbJumpKind == BBJ_SWITCH);
3775     assert(treeNode->OperGet() == GT_JMPTABLE);
3776
3777     unsigned     jumpCount = compiler->compCurBB->bbJumpSwt->bbsCount;
3778     BasicBlock** jumpTable = compiler->compCurBB->bbJumpSwt->bbsDstTab;
3779     unsigned     jmpTabOffs;
3780     unsigned     jmpTabBase;
3781
3782     jmpTabBase = getEmitter()->emitBBTableDataGenBeg(jumpCount, true);
3783
3784     jmpTabOffs = 0;
3785
3786     JITDUMP("\n      J_M%03u_DS%02u LABEL   DWORD\n", Compiler::s_compMethodsCount, jmpTabBase);
3787
3788     for (unsigned i = 0; i < jumpCount; i++)
3789     {
3790         BasicBlock* target = *jumpTable++;
3791         noway_assert(target->bbFlags & BBF_JMP_TARGET);
3792
3793         JITDUMP("            DD      L_M%03u_BB%02u\n", Compiler::s_compMethodsCount, target->bbNum);
3794
3795         getEmitter()->emitDataGenData(i, target);
3796     };
3797
3798     getEmitter()->emitDataGenEnd();
3799
3800     // Access to inline data is 'abstracted' by a special type of static member
3801     // (produced by eeFindJitDataOffs) which the emitter recognizes as being a reference
3802     // to constant data, not a real static field.
3803     getEmitter()->emitIns_R_C(INS_lea, emitTypeSize(TYP_I_IMPL), treeNode->gtRegNum,
3804                               compiler->eeFindJitDataOffs(jmpTabBase), 0);
3805     genProduceReg(treeNode);
3806 }
3807
3808 // generate code for the locked operations:
3809 // GT_LOCKADD, GT_XCHG, GT_XADD
3810 void CodeGen::genLockedInstructions(GenTreeOp* treeNode)
3811 {
3812     GenTree*    data      = treeNode->gtOp.gtOp2;
3813     GenTree*    addr      = treeNode->gtOp.gtOp1;
3814     regNumber   targetReg = treeNode->gtRegNum;
3815     regNumber   dataReg   = data->gtRegNum;
3816     regNumber   addrReg   = addr->gtRegNum;
3817     var_types   type      = genActualType(data->TypeGet());
3818     instruction ins;
3819
3820     // The register allocator should have extended the lifetime of the address
3821     // so that it is not used as the target.
3822     noway_assert(addrReg != targetReg);
3823
3824     // If data is a lclVar that's not a last use, we'd better have allocated a register
3825     // for the result (except in the case of GT_LOCKADD which does not produce a register result).
3826     assert(targetReg != REG_NA || treeNode->OperGet() == GT_LOCKADD || !genIsRegCandidateLocal(data) ||
3827            (data->gtFlags & GTF_VAR_DEATH) != 0);
3828
3829     genConsumeOperands(treeNode);
3830     if (targetReg != REG_NA && dataReg != REG_NA && dataReg != targetReg)
3831     {
3832         inst_RV_RV(ins_Copy(type), targetReg, dataReg);
3833         data->gtRegNum = targetReg;
3834
3835         // TODO-XArch-Cleanup: Consider whether it is worth it, for debugging purposes, to restore the
3836         // original gtRegNum on data, after calling emitInsBinary below.
3837     }
3838     switch (treeNode->OperGet())
3839     {
3840         case GT_LOCKADD:
3841             instGen(INS_lock);
3842             ins = INS_add;
3843             break;
3844         case GT_XCHG:
3845             // lock is implied by xchg
3846             ins = INS_xchg;
3847             break;
3848         case GT_XADD:
3849             instGen(INS_lock);
3850             ins = INS_xadd;
3851             break;
3852         default:
3853             unreached();
3854     }
3855
3856     // all of these nodes implicitly do an indirection on op1
3857     // so create a temporary node to feed into the pattern matching
3858     GenTreeIndir i = indirForm(type, addr);
3859     getEmitter()->emitInsBinary(ins, emitTypeSize(type), &i, data);
3860
3861     if (treeNode->gtRegNum != REG_NA)
3862     {
3863         genProduceReg(treeNode);
3864     }
3865 }
3866
3867 // generate code for BoundsCheck nodes
3868 void CodeGen::genRangeCheck(GenTreePtr oper)
3869 {
3870 #ifdef FEATURE_SIMD
3871     noway_assert(oper->OperGet() == GT_ARR_BOUNDS_CHECK || oper->OperGet() == GT_SIMD_CHK);
3872 #else  // !FEATURE_SIMD
3873     noway_assert(oper->OperGet() == GT_ARR_BOUNDS_CHECK);
3874 #endif // !FEATURE_SIMD
3875
3876     GenTreeBoundsChk* bndsChk = oper->AsBoundsChk();
3877
3878     GenTreePtr arrIndex  = bndsChk->gtIndex;
3879     GenTreePtr arrLen    = bndsChk->gtArrLen;
3880     GenTreePtr arrRef    = nullptr;
3881     int        lenOffset = 0;
3882
3883     GenTree *    src1, *src2;
3884     emitJumpKind jmpKind;
3885
3886     genConsumeRegs(arrIndex);
3887     genConsumeRegs(arrLen);
3888
3889     if (arrIndex->isContainedIntOrIImmed())
3890     {
3891         // arrIndex is a contained constant.  In this case
3892         // we will generate one of the following
3893         //      cmp [mem], immed    (if arrLen is a memory op)
3894         //      cmp reg, immed      (if arrLen is in a reg)
3895         //
3896         // That is arrLen cannot be a contained immed.
3897         assert(!arrLen->isContainedIntOrIImmed());
3898
3899         src1    = arrLen;
3900         src2    = arrIndex;
3901         jmpKind = EJ_jbe;
3902     }
3903     else
3904     {
3905         // arrIndex could either be a contained memory op or a reg
3906         // In this case we will generate one of the following
3907         //      cmp  [mem], immed   (if arrLen is a constant)
3908         //      cmp  [mem], reg     (if arrLen is in a reg)
3909         //      cmp  reg, immed     (if arrIndex is in a reg)
3910         //      cmp  reg1, reg2     (if arraIndex is in reg1)
3911         //      cmp  reg, [mem]     (if arrLen is a memory op)
3912         //
3913         // That is only one of arrIndex or arrLen can be a memory op.
3914         assert(!arrIndex->isUsedFromMemory() || !arrLen->isUsedFromMemory());
3915
3916         src1    = arrIndex;
3917         src2    = arrLen;
3918         jmpKind = EJ_jae;
3919     }
3920
3921     var_types bndsChkType = src2->TypeGet();
3922 #if DEBUG
3923     // Bounds checks can only be 32 or 64 bit sized comparisons.
3924     assert(bndsChkType == TYP_INT || bndsChkType == TYP_LONG);
3925
3926     // The type of the bounds check should always wide enough to compare against the index.
3927     assert(emitTypeSize(bndsChkType) >= emitTypeSize(src1->TypeGet()));
3928 #endif // DEBUG
3929
3930     getEmitter()->emitInsBinary(INS_cmp, emitTypeSize(bndsChkType), src1, src2);
3931     genJumpToThrowHlpBlk(jmpKind, bndsChk->gtThrowKind, bndsChk->gtIndRngFailBB);
3932 }
3933
3934 //------------------------------------------------------------------------
3935 // genOffsetOfMDArrayLowerBound: Returns the offset from the Array object to the
3936 //   lower bound for the given dimension.
3937 //
3938 // Arguments:
3939 //    elemType  - the element type of the array
3940 //    rank      - the rank of the array
3941 //    dimension - the dimension for which the lower bound offset will be returned.
3942 //
3943 // Return Value:
3944 //    The offset.
3945
3946 unsigned CodeGen::genOffsetOfMDArrayLowerBound(var_types elemType, unsigned rank, unsigned dimension)
3947 {
3948     // Note that the lower bound and length fields of the Array object are always TYP_INT, even on 64-bit targets.
3949     return compiler->eeGetArrayDataOffset(elemType) + genTypeSize(TYP_INT) * (dimension + rank);
3950 }
3951
3952 //------------------------------------------------------------------------
3953 // genOffsetOfMDArrayLength: Returns the offset from the Array object to the
3954 //   size for the given dimension.
3955 //
3956 // Arguments:
3957 //    elemType  - the element type of the array
3958 //    rank      - the rank of the array
3959 //    dimension - the dimension for which the lower bound offset will be returned.
3960 //
3961 // Return Value:
3962 //    The offset.
3963
3964 unsigned CodeGen::genOffsetOfMDArrayDimensionSize(var_types elemType, unsigned rank, unsigned dimension)
3965 {
3966     // Note that the lower bound and length fields of the Array object are always TYP_INT, even on 64-bit targets.
3967     return compiler->eeGetArrayDataOffset(elemType) + genTypeSize(TYP_INT) * dimension;
3968 }
3969
3970 //------------------------------------------------------------------------
3971 // genCodeForArrIndex: Generates code to bounds check the index for one dimension of an array reference,
3972 //                     producing the effective index by subtracting the lower bound.
3973 //
3974 // Arguments:
3975 //    arrIndex - the node for which we're generating code
3976 //
3977 // Return Value:
3978 //    None.
3979 //
3980
3981 void CodeGen::genCodeForArrIndex(GenTreeArrIndex* arrIndex)
3982 {
3983     GenTreePtr arrObj    = arrIndex->ArrObj();
3984     GenTreePtr indexNode = arrIndex->IndexExpr();
3985
3986     regNumber arrReg   = genConsumeReg(arrObj);
3987     regNumber indexReg = genConsumeReg(indexNode);
3988     regNumber tgtReg   = arrIndex->gtRegNum;
3989
3990     unsigned  dim      = arrIndex->gtCurrDim;
3991     unsigned  rank     = arrIndex->gtArrRank;
3992     var_types elemType = arrIndex->gtArrElemType;
3993
3994     noway_assert(tgtReg != REG_NA);
3995
3996     // Subtract the lower bound for this dimension.
3997     // TODO-XArch-CQ: make this contained if it's an immediate that fits.
3998     if (tgtReg != indexReg)
3999     {
4000         inst_RV_RV(INS_mov, tgtReg, indexReg, indexNode->TypeGet());
4001     }
4002     getEmitter()->emitIns_R_AR(INS_sub, emitActualTypeSize(TYP_INT), tgtReg, arrReg,
4003                                genOffsetOfMDArrayLowerBound(elemType, rank, dim));
4004     getEmitter()->emitIns_R_AR(INS_cmp, emitActualTypeSize(TYP_INT), tgtReg, arrReg,
4005                                genOffsetOfMDArrayDimensionSize(elemType, rank, dim));
4006     genJumpToThrowHlpBlk(EJ_jae, SCK_RNGCHK_FAIL);
4007
4008     genProduceReg(arrIndex);
4009 }
4010
4011 //------------------------------------------------------------------------
4012 // genCodeForArrOffset: Generates code to compute the flattened array offset for
4013 //    one dimension of an array reference:
4014 //        result = (prevDimOffset * dimSize) + effectiveIndex
4015 //    where dimSize is obtained from the arrObj operand
4016 //
4017 // Arguments:
4018 //    arrOffset - the node for which we're generating code
4019 //
4020 // Return Value:
4021 //    None.
4022 //
4023 // Notes:
4024 //    dimSize and effectiveIndex are always non-negative, the former by design,
4025 //    and the latter because it has been normalized to be zero-based.
4026
4027 void CodeGen::genCodeForArrOffset(GenTreeArrOffs* arrOffset)
4028 {
4029     GenTreePtr offsetNode = arrOffset->gtOffset;
4030     GenTreePtr indexNode  = arrOffset->gtIndex;
4031     GenTreePtr arrObj     = arrOffset->gtArrObj;
4032
4033     regNumber tgtReg = arrOffset->gtRegNum;
4034     assert(tgtReg != REG_NA);
4035
4036     unsigned  dim      = arrOffset->gtCurrDim;
4037     unsigned  rank     = arrOffset->gtArrRank;
4038     var_types elemType = arrOffset->gtArrElemType;
4039
4040     // First, consume the operands in the correct order.
4041     regNumber offsetReg = REG_NA;
4042     regNumber tmpReg    = REG_NA;
4043     if (!offsetNode->IsIntegralConst(0))
4044     {
4045         offsetReg = genConsumeReg(offsetNode);
4046
4047         // We will use a temp register for the offset*scale+effectiveIndex computation.
4048         tmpReg = arrOffset->GetSingleTempReg();
4049     }
4050     else
4051     {
4052         assert(offsetNode->isContained());
4053     }
4054     regNumber indexReg = genConsumeReg(indexNode);
4055     // Although arrReg may not be used in the constant-index case, if we have generated
4056     // the value into a register, we must consume it, otherwise we will fail to end the
4057     // live range of the gc ptr.
4058     // TODO-CQ: Currently arrObj will always have a register allocated to it.
4059     // We could avoid allocating a register for it, which would be of value if the arrObj
4060     // is an on-stack lclVar.
4061     regNumber arrReg = REG_NA;
4062     if (arrObj->gtHasReg())
4063     {
4064         arrReg = genConsumeReg(arrObj);
4065     }
4066
4067     if (!offsetNode->IsIntegralConst(0))
4068     {
4069         assert(tmpReg != REG_NA);
4070         assert(arrReg != REG_NA);
4071
4072         // Evaluate tgtReg = offsetReg*dim_size + indexReg.
4073         // tmpReg is used to load dim_size and the result of the multiplication.
4074         // Note that dim_size will never be negative.
4075
4076         getEmitter()->emitIns_R_AR(INS_mov, emitActualTypeSize(TYP_INT), tmpReg, arrReg,
4077                                    genOffsetOfMDArrayDimensionSize(elemType, rank, dim));
4078         inst_RV_RV(INS_imul, tmpReg, offsetReg);
4079
4080         if (tmpReg == tgtReg)
4081         {
4082             inst_RV_RV(INS_add, tmpReg, indexReg);
4083         }
4084         else
4085         {
4086             if (indexReg != tgtReg)
4087             {
4088                 inst_RV_RV(INS_mov, tgtReg, indexReg, TYP_I_IMPL);
4089             }
4090             inst_RV_RV(INS_add, tgtReg, tmpReg);
4091         }
4092     }
4093     else
4094     {
4095         if (indexReg != tgtReg)
4096         {
4097             inst_RV_RV(INS_mov, tgtReg, indexReg, TYP_INT);
4098         }
4099     }
4100     genProduceReg(arrOffset);
4101 }
4102
4103 // make a temporary indir we can feed to pattern matching routines
4104 // in cases where we don't want to instantiate all the indirs that happen
4105 //
4106 GenTreeIndir CodeGen::indirForm(var_types type, GenTree* base)
4107 {
4108     GenTreeIndir i(GT_IND, type, base, nullptr);
4109     i.gtRegNum = REG_NA;
4110     // has to be nonnull (because contained nodes can't be the last in block)
4111     // but don't want it to be a valid pointer
4112     i.gtNext = (GenTree*)(-1);
4113     return i;
4114 }
4115
4116 // make a temporary int we can feed to pattern matching routines
4117 // in cases where we don't want to instantiate
4118 //
4119 GenTreeIntCon CodeGen::intForm(var_types type, ssize_t value)
4120 {
4121     GenTreeIntCon i(type, value);
4122     i.gtRegNum = REG_NA;
4123     // has to be nonnull (because contained nodes can't be the last in block)
4124     // but don't want it to be a valid pointer
4125     i.gtNext = (GenTree*)(-1);
4126     return i;
4127 }
4128
4129 instruction CodeGen::genGetInsForOper(genTreeOps oper, var_types type)
4130 {
4131     instruction ins;
4132
4133     // Operations on SIMD vectors shouldn't come this path
4134     assert(!varTypeIsSIMD(type));
4135     if (varTypeIsFloating(type))
4136     {
4137         return ins_MathOp(oper, type);
4138     }
4139
4140     switch (oper)
4141     {
4142         case GT_ADD:
4143             ins = INS_add;
4144             break;
4145         case GT_AND:
4146             ins = INS_and;
4147             break;
4148         case GT_LSH:
4149             ins = INS_shl;
4150             break;
4151         case GT_MUL:
4152             ins = INS_imul;
4153             break;
4154         case GT_NEG:
4155             ins = INS_neg;
4156             break;
4157         case GT_NOT:
4158             ins = INS_not;
4159             break;
4160         case GT_OR:
4161             ins = INS_or;
4162             break;
4163         case GT_ROL:
4164             ins = INS_rol;
4165             break;
4166         case GT_ROR:
4167             ins = INS_ror;
4168             break;
4169         case GT_RSH:
4170             ins = INS_sar;
4171             break;
4172         case GT_RSZ:
4173             ins = INS_shr;
4174             break;
4175         case GT_SUB:
4176             ins = INS_sub;
4177             break;
4178         case GT_XOR:
4179             ins = INS_xor;
4180             break;
4181 #if !defined(_TARGET_64BIT_)
4182         case GT_ADD_LO:
4183             ins = INS_add;
4184             break;
4185         case GT_ADD_HI:
4186             ins = INS_adc;
4187             break;
4188         case GT_SUB_LO:
4189             ins = INS_sub;
4190             break;
4191         case GT_SUB_HI:
4192             ins = INS_sbb;
4193             break;
4194         case GT_LSH_HI:
4195             ins = INS_shld;
4196             break;
4197         case GT_RSH_LO:
4198             ins = INS_shrd;
4199             break;
4200 #endif // !defined(_TARGET_64BIT_)
4201         default:
4202             unreached();
4203             break;
4204     }
4205     return ins;
4206 }
4207
4208 //------------------------------------------------------------------------
4209 // genCodeForShift: Generates the code sequence for a GenTree node that
4210 // represents a bit shift or rotate operation (<<, >>, >>>, rol, ror).
4211 //
4212 // Arguments:
4213 //    tree - the bit shift node (that specifies the type of bit shift to perform).
4214 //
4215 // Assumptions:
4216 //    a) All GenTrees are register allocated.
4217 //    b) The shift-by-amount in tree->gtOp.gtOp2 is either a contained constant or
4218 //       it's a register-allocated expression. If it is in a register that is
4219 //       not RCX, it will be moved to RCX (so RCX better not be in use!).
4220 //
4221 void CodeGen::genCodeForShift(GenTreePtr tree)
4222 {
4223     // Only the non-RMW case here.
4224     assert(tree->OperIsShiftOrRotate());
4225     assert(tree->gtOp.gtOp1->isUsedFromReg());
4226     assert(tree->gtRegNum != REG_NA);
4227
4228     genConsumeOperands(tree->AsOp());
4229
4230     var_types   targetType = tree->TypeGet();
4231     instruction ins        = genGetInsForOper(tree->OperGet(), targetType);
4232
4233     GenTreePtr operand    = tree->gtGetOp1();
4234     regNumber  operandReg = operand->gtRegNum;
4235
4236     GenTreePtr shiftBy = tree->gtGetOp2();
4237
4238     if (shiftBy->isContainedIntOrIImmed())
4239     {
4240         // First, move the operand to the destination register and
4241         // later on perform the shift in-place.
4242         // (LSRA will try to avoid this situation through preferencing.)
4243         if (tree->gtRegNum != operandReg)
4244         {
4245             inst_RV_RV(INS_mov, tree->gtRegNum, operandReg, targetType);
4246         }
4247
4248         int shiftByValue = (int)shiftBy->AsIntConCommon()->IconValue();
4249         inst_RV_SH(ins, emitTypeSize(tree), tree->gtRegNum, shiftByValue);
4250     }
4251     else
4252     {
4253         // We must have the number of bits to shift stored in ECX, since we constrained this node to
4254         // sit in ECX. In case this didn't happen, LSRA expects the code generator to move it since it's a single
4255         // register destination requirement.
4256         genCopyRegIfNeeded(shiftBy, REG_RCX);
4257
4258         // The operand to be shifted must not be in ECX
4259         noway_assert(operandReg != REG_RCX);
4260
4261         if (tree->gtRegNum != operandReg)
4262         {
4263             inst_RV_RV(INS_mov, tree->gtRegNum, operandReg, targetType);
4264         }
4265         inst_RV_CL(ins, tree->gtRegNum, targetType);
4266     }
4267
4268     genProduceReg(tree);
4269 }
4270
4271 #ifdef _TARGET_X86_
4272 //------------------------------------------------------------------------
4273 // genCodeForShiftLong: Generates the code sequence for a GenTree node that
4274 // represents a three operand bit shift or rotate operation (<<Hi, >>Lo).
4275 //
4276 // Arguments:
4277 //    tree - the bit shift node (that specifies the type of bit shift to perform).
4278 //
4279 // Assumptions:
4280 //    a) All GenTrees are register allocated.
4281 //    b) The shift-by-amount in tree->gtOp.gtOp2 is a contained constant
4282 //
4283 void CodeGen::genCodeForShiftLong(GenTreePtr tree)
4284 {
4285     // Only the non-RMW case here.
4286     genTreeOps oper = tree->OperGet();
4287     assert(oper == GT_LSH_HI || oper == GT_RSH_LO);
4288
4289     GenTree* operand = tree->gtOp.gtOp1;
4290     assert(operand->OperGet() == GT_LONG);
4291     assert(operand->gtOp.gtOp1->isUsedFromReg());
4292     assert(operand->gtOp.gtOp2->isUsedFromReg());
4293
4294     GenTree* operandLo = operand->gtGetOp1();
4295     GenTree* operandHi = operand->gtGetOp2();
4296
4297     regNumber regLo = operandLo->gtRegNum;
4298     regNumber regHi = operandHi->gtRegNum;
4299
4300     genConsumeOperands(tree->AsOp());
4301
4302     var_types   targetType = tree->TypeGet();
4303     instruction ins        = genGetInsForOper(oper, targetType);
4304
4305     GenTreePtr shiftBy = tree->gtGetOp2();
4306
4307     assert(shiftBy->isContainedIntOrIImmed());
4308
4309     unsigned int count = shiftBy->AsIntConCommon()->IconValue();
4310
4311     regNumber regResult = (oper == GT_LSH_HI) ? regHi : regLo;
4312
4313     if (regResult != tree->gtRegNum)
4314     {
4315         inst_RV_RV(INS_mov, tree->gtRegNum, regResult, targetType);
4316     }
4317
4318     if (oper == GT_LSH_HI)
4319     {
4320         inst_RV_RV_IV(ins, emitTypeSize(targetType), tree->gtRegNum, regLo, count);
4321     }
4322     else
4323     {
4324         assert(oper == GT_RSH_LO);
4325         inst_RV_RV_IV(ins, emitTypeSize(targetType), tree->gtRegNum, regHi, count);
4326     }
4327
4328     genProduceReg(tree);
4329 }
4330 #endif
4331
4332 //------------------------------------------------------------------------
4333 // genCodeForShiftRMW: Generates the code sequence for a GT_STOREIND GenTree node that
4334 // represents a RMW bit shift or rotate operation (<<, >>, >>>, rol, ror), for example:
4335 //      GT_STOREIND( AddressTree, GT_SHL( Ind ( AddressTree ), Operand ) )
4336 //
4337 // Arguments:
4338 //    storeIndNode: the GT_STOREIND node.
4339 //
4340 void CodeGen::genCodeForShiftRMW(GenTreeStoreInd* storeInd)
4341 {
4342     GenTree* data = storeInd->Data();
4343     GenTree* addr = storeInd->Addr();
4344
4345     assert(data->OperIsShiftOrRotate());
4346
4347     // This function only handles the RMW case.
4348     assert(data->gtOp.gtOp1->isUsedFromMemory());
4349     assert(data->gtOp.gtOp1->isIndir());
4350     assert(Lowering::IndirsAreEquivalent(data->gtOp.gtOp1, storeInd));
4351     assert(data->gtRegNum == REG_NA);
4352
4353     var_types   targetType = data->TypeGet();
4354     genTreeOps  oper       = data->OperGet();
4355     instruction ins        = genGetInsForOper(oper, targetType);
4356     emitAttr    attr       = EA_ATTR(genTypeSize(targetType));
4357
4358     GenTree* shiftBy = data->gtOp.gtOp2;
4359     if (shiftBy->isContainedIntOrIImmed())
4360     {
4361         int shiftByValue = (int)shiftBy->AsIntConCommon()->IconValue();
4362         ins              = genMapShiftInsToShiftByConstantIns(ins, shiftByValue);
4363         if (shiftByValue == 1)
4364         {
4365             // There is no source in this case, as the shift by count is embedded in the instruction opcode itself.
4366             getEmitter()->emitInsRMW(ins, attr, storeInd);
4367         }
4368         else
4369         {
4370             getEmitter()->emitInsRMW(ins, attr, storeInd, shiftBy);
4371         }
4372     }
4373     else
4374     {
4375         // We must have the number of bits to shift stored in ECX, since we constrained this node to
4376         // sit in ECX. In case this didn't happen, LSRA expects the code generator to move it since it's a single
4377         // register destination requirement.
4378         regNumber shiftReg = shiftBy->gtRegNum;
4379         genCopyRegIfNeeded(shiftBy, REG_RCX);
4380
4381         // The shiftBy operand is implicit, so call the unary version of emitInsRMW.
4382         getEmitter()->emitInsRMW(ins, attr, storeInd);
4383     }
4384 }
4385
4386 void CodeGen::genRegCopy(GenTree* treeNode)
4387 {
4388     assert(treeNode->OperGet() == GT_COPY);
4389     GenTree* op1 = treeNode->gtOp.gtOp1;
4390
4391     if (op1->IsMultiRegCall())
4392     {
4393         genConsumeReg(op1);
4394
4395         GenTreeCopyOrReload* copyTree    = treeNode->AsCopyOrReload();
4396         GenTreeCall*         call        = op1->AsCall();
4397         ReturnTypeDesc*      retTypeDesc = call->GetReturnTypeDesc();
4398         unsigned             regCount    = retTypeDesc->GetReturnRegCount();
4399
4400         for (unsigned i = 0; i < regCount; ++i)
4401         {
4402             var_types type    = retTypeDesc->GetReturnRegType(i);
4403             regNumber fromReg = call->GetRegNumByIdx(i);
4404             regNumber toReg   = copyTree->GetRegNumByIdx(i);
4405
4406             // A Multi-reg GT_COPY node will have valid reg only for those
4407             // positions that corresponding result reg of call node needs
4408             // to be copied.
4409             if (toReg != REG_NA)
4410             {
4411                 assert(toReg != fromReg);
4412                 inst_RV_RV(ins_Copy(type), toReg, fromReg, type);
4413             }
4414         }
4415     }
4416     else
4417     {
4418         var_types targetType = treeNode->TypeGet();
4419         regNumber targetReg  = treeNode->gtRegNum;
4420         assert(targetReg != REG_NA);
4421
4422         // Check whether this node and the node from which we're copying the value have
4423         // different register types. This can happen if (currently iff) we have a SIMD
4424         // vector type that fits in an integer register, in which case it is passed as
4425         // an argument, or returned from a call, in an integer register and must be
4426         // copied if it's in an xmm register.
4427
4428         bool srcFltReg = (varTypeIsFloating(op1) || varTypeIsSIMD(op1));
4429         bool tgtFltReg = (varTypeIsFloating(treeNode) || varTypeIsSIMD(treeNode));
4430         if (srcFltReg != tgtFltReg)
4431         {
4432             instruction ins;
4433             regNumber   fpReg;
4434             regNumber   intReg;
4435             if (tgtFltReg)
4436             {
4437                 ins    = ins_CopyIntToFloat(op1->TypeGet(), treeNode->TypeGet());
4438                 fpReg  = targetReg;
4439                 intReg = op1->gtRegNum;
4440             }
4441             else
4442             {
4443                 ins    = ins_CopyFloatToInt(op1->TypeGet(), treeNode->TypeGet());
4444                 intReg = targetReg;
4445                 fpReg  = op1->gtRegNum;
4446             }
4447             inst_RV_RV(ins, fpReg, intReg, targetType);
4448         }
4449         else
4450         {
4451             inst_RV_RV(ins_Copy(targetType), targetReg, genConsumeReg(op1), targetType);
4452         }
4453
4454         if (op1->IsLocal())
4455         {
4456             // The lclVar will never be a def.
4457             // If it is a last use, the lclVar will be killed by genConsumeReg(), as usual, and genProduceReg will
4458             // appropriately set the gcInfo for the copied value.
4459             // If not, there are two cases we need to handle:
4460             // - If this is a TEMPORARY copy (indicated by the GTF_VAR_DEATH flag) the variable
4461             //   will remain live in its original register.
4462             //   genProduceReg() will appropriately set the gcInfo for the copied value,
4463             //   and genConsumeReg will reset it.
4464             // - Otherwise, we need to update register info for the lclVar.
4465
4466             GenTreeLclVarCommon* lcl = op1->AsLclVarCommon();
4467             assert((lcl->gtFlags & GTF_VAR_DEF) == 0);
4468
4469             if ((lcl->gtFlags & GTF_VAR_DEATH) == 0 && (treeNode->gtFlags & GTF_VAR_DEATH) == 0)
4470             {
4471                 LclVarDsc* varDsc = &compiler->lvaTable[lcl->gtLclNum];
4472
4473                 // If we didn't just spill it (in genConsumeReg, above), then update the register info
4474                 if (varDsc->lvRegNum != REG_STK)
4475                 {
4476                     // The old location is dying
4477                     genUpdateRegLife(varDsc, /*isBorn*/ false, /*isDying*/ true DEBUGARG(op1));
4478
4479                     gcInfo.gcMarkRegSetNpt(genRegMask(op1->gtRegNum));
4480
4481                     genUpdateVarReg(varDsc, treeNode);
4482
4483                     // The new location is going live
4484                     genUpdateRegLife(varDsc, /*isBorn*/ true, /*isDying*/ false DEBUGARG(treeNode));
4485                 }
4486             }
4487         }
4488     }
4489
4490     genProduceReg(treeNode);
4491 }
4492
4493 //------------------------------------------------------------------------
4494 // genStoreInd: Generate code for a GT_STOREIND node.
4495 //
4496 // Arguments:
4497 //    treeNode - The GT_STOREIND node for which to generate code.
4498 //
4499 // Return Value:
4500 //    none
4501
4502 void CodeGen::genStoreInd(GenTreePtr node)
4503 {
4504     assert(node->OperGet() == GT_STOREIND);
4505
4506 #ifdef FEATURE_SIMD
4507     // Storing Vector3 of size 12 bytes through indirection
4508     if (node->TypeGet() == TYP_SIMD12)
4509     {
4510         genStoreIndTypeSIMD12(node);
4511         return;
4512     }
4513 #endif // FEATURE_SIMD
4514
4515     GenTreeStoreInd* storeInd   = node->AsStoreInd();
4516     GenTree*         data       = storeInd->Data();
4517     GenTree*         addr       = storeInd->Addr();
4518     var_types        targetType = storeInd->TypeGet();
4519
4520     assert(!varTypeIsFloating(targetType) || (targetType == data->TypeGet()));
4521
4522     GCInfo::WriteBarrierForm writeBarrierForm = gcInfo.gcIsWriteBarrierCandidate(storeInd, data);
4523     if (writeBarrierForm != GCInfo::WBF_NoBarrier)
4524     {
4525         // data and addr must be in registers.
4526         // Consume both registers so that any copies of interfering registers are taken care of.
4527         genConsumeOperands(storeInd->AsOp());
4528
4529         if (genEmitOptimizedGCWriteBarrier(writeBarrierForm, addr, data))
4530         {
4531             return;
4532         }
4533
4534         // At this point, we should not have any interference.
4535         // That is, 'data' must not be in REG_ARG_0, as that is where 'addr' must go.
4536         noway_assert(data->gtRegNum != REG_ARG_0);
4537
4538         // addr goes in REG_ARG_0
4539         genCopyRegIfNeeded(addr, REG_ARG_0);
4540
4541         // data goes in REG_ARG_1
4542         genCopyRegIfNeeded(data, REG_ARG_1);
4543
4544         genGCWriteBarrier(storeInd, writeBarrierForm);
4545     }
4546     else
4547     {
4548         bool     reverseOps    = ((storeInd->gtFlags & GTF_REVERSE_OPS) != 0);
4549         bool     dataIsUnary   = false;
4550         bool     isRMWMemoryOp = storeInd->IsRMWMemoryOp();
4551         GenTree* rmwSrc        = nullptr;
4552
4553         // We must consume the operands in the proper execution order, so that liveness is
4554         // updated appropriately.
4555         if (!reverseOps)
4556         {
4557             genConsumeAddress(addr);
4558         }
4559
4560         // If storeInd represents a RMW memory op then its data is a non-leaf node marked as contained
4561         // and non-indir operand of data is the source of RMW memory op.
4562         if (isRMWMemoryOp)
4563         {
4564             assert(data->isContained() && !data->OperIsLeaf());
4565
4566             GenTreePtr rmwDst = nullptr;
4567
4568             dataIsUnary = (GenTree::OperIsUnary(data->OperGet()) != 0);
4569             if (!dataIsUnary)
4570             {
4571                 if (storeInd->IsRMWDstOp1())
4572                 {
4573                     rmwDst = data->gtGetOp1();
4574                     rmwSrc = data->gtGetOp2();
4575                 }
4576                 else
4577                 {
4578                     assert(storeInd->IsRMWDstOp2());
4579                     rmwDst = data->gtGetOp2();
4580                     rmwSrc = data->gtGetOp1();
4581                 }
4582
4583                 genConsumeRegs(rmwSrc);
4584             }
4585             else
4586             {
4587                 // *(p) = oper *(p): Here addr = p, rmwsrc=rmwDst = *(p) i.e. GT_IND(p)
4588                 // For unary RMW ops, src and dst of RMW memory op is the same.  Lower
4589                 // clears operand counts on rmwSrc and we don't need to perform a
4590                 // genConsumeReg() on it.
4591                 assert(storeInd->IsRMWDstOp1());
4592                 rmwSrc = data->gtGetOp1();
4593                 rmwDst = data->gtGetOp1();
4594                 assert(rmwSrc->isUsedFromMemory());
4595             }
4596
4597             assert(rmwSrc != nullptr);
4598             assert(rmwDst != nullptr);
4599             assert(Lowering::IndirsAreEquivalent(rmwDst, storeInd));
4600         }
4601         else
4602         {
4603             genConsumeRegs(data);
4604         }
4605
4606         if (reverseOps)
4607         {
4608             genConsumeAddress(addr);
4609         }
4610
4611         if (isRMWMemoryOp)
4612         {
4613             if (dataIsUnary)
4614             {
4615                 // generate code for unary RMW memory ops like neg/not
4616                 getEmitter()->emitInsRMW(genGetInsForOper(data->OperGet(), data->TypeGet()), emitTypeSize(storeInd),
4617                                          storeInd);
4618             }
4619             else
4620             {
4621                 if (data->OperIsShiftOrRotate())
4622                 {
4623                     // Generate code for shift RMW memory ops.
4624                     // The data address needs to be op1 (it must be [addr] = [addr] <shift> <amount>, not [addr] =
4625                     // <amount> <shift> [addr]).
4626                     assert(storeInd->IsRMWDstOp1());
4627                     assert(rmwSrc == data->gtGetOp2());
4628                     genCodeForShiftRMW(storeInd);
4629                 }
4630                 else if (data->OperGet() == GT_ADD && (rmwSrc->IsIntegralConst(1) || rmwSrc->IsIntegralConst(-1)))
4631                 {
4632                     // Generate "inc/dec [mem]" instead of "add/sub [mem], 1".
4633                     //
4634                     // Notes:
4635                     //  1) Global morph transforms GT_SUB(x, +/-1) into GT_ADD(x, -/+1).
4636                     //  2) TODO-AMD64: Debugger routine NativeWalker::Decode() runs into
4637                     //     an assert while decoding ModR/M byte of "inc dword ptr [rax]".
4638                     //     It is not clear whether Decode() can handle all possible
4639                     //     addr modes with inc/dec.  For this reason, inc/dec [mem]
4640                     //     is not generated while generating debuggable code.  Update
4641                     //     the above if condition once Decode() routine is fixed.
4642                     assert(rmwSrc->isContainedIntOrIImmed());
4643                     instruction ins = rmwSrc->IsIntegralConst(1) ? INS_inc : INS_dec;
4644                     getEmitter()->emitInsRMW(ins, emitTypeSize(storeInd), storeInd);
4645                 }
4646                 else
4647                 {
4648                     // generate code for remaining binary RMW memory ops like add/sub/and/or/xor
4649                     getEmitter()->emitInsRMW(genGetInsForOper(data->OperGet(), data->TypeGet()), emitTypeSize(storeInd),
4650                                              storeInd, rmwSrc);
4651                 }
4652             }
4653         }
4654         else
4655         {
4656             getEmitter()->emitInsMov(ins_Store(data->TypeGet()), emitTypeSize(storeInd), storeInd);
4657         }
4658     }
4659 }
4660
4661 //------------------------------------------------------------------------
4662 // genEmitOptimizedGCWriteBarrier: Generate write barrier store using the optimized
4663 // helper functions.
4664 //
4665 // Arguments:
4666 //    writeBarrierForm - the write barrier form to use
4667 //    addr - the address at which to do the store
4668 //    data - the data to store
4669 //
4670 // Return Value:
4671 //    true if an optimized write barrier form was used, false if not. If this
4672 //    function returns false, the caller must emit a "standard" write barrier.
4673
4674 bool CodeGen::genEmitOptimizedGCWriteBarrier(GCInfo::WriteBarrierForm writeBarrierForm, GenTree* addr, GenTree* data)
4675 {
4676     assert(writeBarrierForm != GCInfo::WBF_NoBarrier);
4677
4678 #if defined(_TARGET_X86_) && NOGC_WRITE_BARRIERS
4679     bool useOptimizedWriteBarriers = true;
4680
4681 #ifdef DEBUG
4682     useOptimizedWriteBarriers =
4683         (writeBarrierForm != GCInfo::WBF_NoBarrier_CheckNotHeapInDebug); // This one is always a call to a C++ method.
4684 #endif
4685
4686     if (!useOptimizedWriteBarriers)
4687     {
4688         return false;
4689     }
4690
4691     const static int regToHelper[2][8] = {
4692         // If the target is known to be in managed memory
4693         {
4694             CORINFO_HELP_ASSIGN_REF_EAX, CORINFO_HELP_ASSIGN_REF_ECX, -1, CORINFO_HELP_ASSIGN_REF_EBX, -1,
4695             CORINFO_HELP_ASSIGN_REF_EBP, CORINFO_HELP_ASSIGN_REF_ESI, CORINFO_HELP_ASSIGN_REF_EDI,
4696         },
4697
4698         // Don't know if the target is in managed memory
4699         {
4700             CORINFO_HELP_CHECKED_ASSIGN_REF_EAX, CORINFO_HELP_CHECKED_ASSIGN_REF_ECX, -1,
4701             CORINFO_HELP_CHECKED_ASSIGN_REF_EBX, -1, CORINFO_HELP_CHECKED_ASSIGN_REF_EBP,
4702             CORINFO_HELP_CHECKED_ASSIGN_REF_ESI, CORINFO_HELP_CHECKED_ASSIGN_REF_EDI,
4703         },
4704     };
4705
4706     noway_assert(regToHelper[0][REG_EAX] == CORINFO_HELP_ASSIGN_REF_EAX);
4707     noway_assert(regToHelper[0][REG_ECX] == CORINFO_HELP_ASSIGN_REF_ECX);
4708     noway_assert(regToHelper[0][REG_EBX] == CORINFO_HELP_ASSIGN_REF_EBX);
4709     noway_assert(regToHelper[0][REG_ESP] == -1);
4710     noway_assert(regToHelper[0][REG_EBP] == CORINFO_HELP_ASSIGN_REF_EBP);
4711     noway_assert(regToHelper[0][REG_ESI] == CORINFO_HELP_ASSIGN_REF_ESI);
4712     noway_assert(regToHelper[0][REG_EDI] == CORINFO_HELP_ASSIGN_REF_EDI);
4713
4714     noway_assert(regToHelper[1][REG_EAX] == CORINFO_HELP_CHECKED_ASSIGN_REF_EAX);
4715     noway_assert(regToHelper[1][REG_ECX] == CORINFO_HELP_CHECKED_ASSIGN_REF_ECX);
4716     noway_assert(regToHelper[1][REG_EBX] == CORINFO_HELP_CHECKED_ASSIGN_REF_EBX);
4717     noway_assert(regToHelper[1][REG_ESP] == -1);
4718     noway_assert(regToHelper[1][REG_EBP] == CORINFO_HELP_CHECKED_ASSIGN_REF_EBP);
4719     noway_assert(regToHelper[1][REG_ESI] == CORINFO_HELP_CHECKED_ASSIGN_REF_ESI);
4720     noway_assert(regToHelper[1][REG_EDI] == CORINFO_HELP_CHECKED_ASSIGN_REF_EDI);
4721
4722     regNumber reg = data->gtRegNum;
4723     noway_assert((reg != REG_ESP) && (reg != REG_WRITE_BARRIER));
4724
4725     // Generate the following code:
4726     //            lea     edx, addr
4727     //            call    write_barrier_helper_reg
4728
4729     // addr goes in REG_ARG_0
4730     genCopyRegIfNeeded(addr, REG_WRITE_BARRIER);
4731
4732     unsigned tgtAnywhere = 0;
4733     if (writeBarrierForm != GCInfo::WBF_BarrierUnchecked)
4734     {
4735         tgtAnywhere = 1;
4736     }
4737
4738     // We might want to call a modified version of genGCWriteBarrier() to get the benefit of
4739     // the FEATURE_COUNT_GC_WRITE_BARRIERS code there, but that code doesn't look like it works
4740     // with rationalized RyuJIT IR. So, for now, just emit the helper call directly here.
4741
4742     genEmitHelperCall(regToHelper[tgtAnywhere][reg],
4743                       0,           // argSize
4744                       EA_PTRSIZE); // retSize
4745
4746     return true;
4747 #else  // !defined(_TARGET_X86_) || !NOGC_WRITE_BARRIERS
4748     return false;
4749 #endif // !defined(_TARGET_X86_) || !NOGC_WRITE_BARRIERS
4750 }
4751
4752 // Produce code for a GT_CALL node
4753 void CodeGen::genCallInstruction(GenTreeCall* call)
4754 {
4755     genAlignStackBeforeCall(call);
4756
4757     gtCallTypes callType = (gtCallTypes)call->gtCallType;
4758
4759     IL_OFFSETX ilOffset = BAD_IL_OFFSET;
4760
4761     // all virtuals should have been expanded into a control expression
4762     assert(!call->IsVirtual() || call->gtControlExpr || call->gtCallAddr);
4763
4764     // Insert a GS check if necessary
4765     if (call->IsTailCallViaHelper())
4766     {
4767         if (compiler->getNeedsGSSecurityCookie())
4768         {
4769 #if FEATURE_FIXED_OUT_ARGS
4770             // If either of the conditions below is true, we will need a temporary register in order to perform the GS
4771             // cookie check. When FEATURE_FIXED_OUT_ARGS is disabled, we save and restore the temporary register using
4772             // push/pop. When FEATURE_FIXED_OUT_ARGS is enabled, however, we need an alternative solution. For now,
4773             // though, the tail prefix is ignored on all platforms that use fixed out args, so we should never hit this
4774             // case.
4775             assert(compiler->gsGlobalSecurityCookieAddr == nullptr);
4776             assert((int)compiler->gsGlobalSecurityCookieVal == (ssize_t)compiler->gsGlobalSecurityCookieVal);
4777 #endif
4778             genEmitGSCookieCheck(true);
4779         }
4780     }
4781
4782     // Consume all the arg regs
4783     for (GenTreePtr list = call->gtCallLateArgs; list; list = list->MoveNext())
4784     {
4785         assert(list->OperIsList());
4786
4787         GenTreePtr argNode = list->Current();
4788
4789         fgArgTabEntryPtr curArgTabEntry = compiler->gtArgEntryByNode(call, argNode->gtSkipReloadOrCopy());
4790         assert(curArgTabEntry);
4791
4792         if (curArgTabEntry->regNum == REG_STK)
4793         {
4794             continue;
4795         }
4796
4797 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
4798         // Deal with multi register passed struct args.
4799         if (argNode->OperGet() == GT_FIELD_LIST)
4800         {
4801             GenTreeFieldList* fieldListPtr = argNode->AsFieldList();
4802             unsigned          iterationNum = 0;
4803             for (; fieldListPtr != nullptr; fieldListPtr = fieldListPtr->Rest(), iterationNum++)
4804             {
4805                 GenTreePtr putArgRegNode = fieldListPtr->gtOp.gtOp1;
4806                 assert(putArgRegNode->gtOper == GT_PUTARG_REG);
4807                 regNumber argReg = REG_NA;
4808
4809                 if (iterationNum == 0)
4810                 {
4811                     argReg = curArgTabEntry->regNum;
4812                 }
4813                 else
4814                 {
4815                     assert(iterationNum == 1);
4816                     argReg = curArgTabEntry->otherRegNum;
4817                 }
4818
4819                 genConsumeReg(putArgRegNode);
4820
4821                 // Validate the putArgRegNode has the right type.
4822                 assert(putArgRegNode->TypeGet() ==
4823                        compiler->GetTypeFromClassificationAndSizes(curArgTabEntry->structDesc
4824                                                                        .eightByteClassifications[iterationNum],
4825                                                                    curArgTabEntry->structDesc
4826                                                                        .eightByteSizes[iterationNum]));
4827                 if (putArgRegNode->gtRegNum != argReg)
4828                 {
4829                     inst_RV_RV(ins_Move_Extend(putArgRegNode->TypeGet(), putArgRegNode->InReg()), argReg,
4830                                putArgRegNode->gtRegNum);
4831                 }
4832             }
4833         }
4834         else
4835 #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
4836         {
4837             regNumber argReg = curArgTabEntry->regNum;
4838             genConsumeReg(argNode);
4839             if (argNode->gtRegNum != argReg)
4840             {
4841                 inst_RV_RV(ins_Move_Extend(argNode->TypeGet(), argNode->InReg()), argReg, argNode->gtRegNum);
4842             }
4843         }
4844
4845 #if FEATURE_VARARG
4846         // In the case of a varargs call,
4847         // the ABI dictates that if we have floating point args,
4848         // we must pass the enregistered arguments in both the
4849         // integer and floating point registers so, let's do that.
4850         if (call->IsVarargs() && varTypeIsFloating(argNode))
4851         {
4852             regNumber   targetReg = compiler->getCallArgIntRegister(argNode->gtRegNum);
4853             instruction ins       = ins_CopyFloatToInt(argNode->TypeGet(), TYP_LONG);
4854             inst_RV_RV(ins, argNode->gtRegNum, targetReg);
4855         }
4856 #endif // FEATURE_VARARG
4857     }
4858
4859 #if defined(_TARGET_X86_) || defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
4860     // The call will pop its arguments.
4861     // for each putarg_stk:
4862     ssize_t    stackArgBytes = 0;
4863     GenTreePtr args          = call->gtCallArgs;
4864     while (args)
4865     {
4866         GenTreePtr arg = args->gtOp.gtOp1;
4867         if (arg->OperGet() != GT_ARGPLACE && !(arg->gtFlags & GTF_LATE_ARG))
4868         {
4869 #if defined(_TARGET_X86_)
4870             if ((arg->OperGet() == GT_PUTARG_STK) && (arg->gtGetOp1()->OperGet() == GT_FIELD_LIST))
4871             {
4872                 fgArgTabEntryPtr curArgTabEntry = compiler->gtArgEntryByNode(call, arg);
4873                 assert(curArgTabEntry);
4874                 stackArgBytes += curArgTabEntry->numSlots * TARGET_POINTER_SIZE;
4875             }
4876             else
4877 #endif // defined(_TARGET_X86_)
4878
4879 #ifdef FEATURE_PUT_STRUCT_ARG_STK
4880                 if (genActualType(arg->TypeGet()) == TYP_STRUCT)
4881             {
4882                 assert(arg->OperGet() == GT_PUTARG_STK);
4883
4884                 GenTreeObj* obj      = arg->gtGetOp1()->AsObj();
4885                 unsigned    argBytes = (unsigned)roundUp(obj->gtBlkSize, TARGET_POINTER_SIZE);
4886 #ifdef DEBUG
4887                 fgArgTabEntryPtr curArgTabEntry = compiler->gtArgEntryByNode(call, arg);
4888                 assert((curArgTabEntry->numSlots * TARGET_POINTER_SIZE) == argBytes);
4889 #endif // DEBUG
4890                 stackArgBytes += argBytes;
4891             }
4892             else
4893 #endif // FEATURE_PUT_STRUCT_ARG_STK
4894
4895             {
4896                 stackArgBytes += genTypeSize(genActualType(arg->TypeGet()));
4897             }
4898         }
4899         args = args->gtOp.gtOp2;
4900     }
4901 #endif // defined(_TARGET_X86_) || defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
4902
4903     // Insert a null check on "this" pointer if asked.
4904     if (call->NeedsNullCheck())
4905     {
4906         const regNumber regThis = genGetThisArgReg(call);
4907         getEmitter()->emitIns_AR_R(INS_cmp, EA_4BYTE, regThis, regThis, 0);
4908     }
4909
4910     // Either gtControlExpr != null or gtCallAddr != null or it is a direct non-virtual call to a user or helper method.
4911     CORINFO_METHOD_HANDLE methHnd;
4912     GenTree*              target = call->gtControlExpr;
4913     if (callType == CT_INDIRECT)
4914     {
4915         assert(target == nullptr);
4916         target  = call->gtCallAddr;
4917         methHnd = nullptr;
4918     }
4919     else
4920     {
4921         methHnd = call->gtCallMethHnd;
4922     }
4923
4924     CORINFO_SIG_INFO* sigInfo = nullptr;
4925 #ifdef DEBUG
4926     // Pass the call signature information down into the emitter so the emitter can associate
4927     // native call sites with the signatures they were generated from.
4928     if (callType != CT_HELPER)
4929     {
4930         sigInfo = call->callSig;
4931     }
4932 #endif // DEBUG
4933
4934     // If fast tail call, then we are done.  In this case we setup the args (both reg args
4935     // and stack args in incoming arg area) and call target in rax.  Epilog sequence would
4936     // generate "jmp rax".
4937     if (call->IsFastTailCall())
4938     {
4939         // Don't support fast tail calling JIT helpers
4940         assert(callType != CT_HELPER);
4941
4942         // Fast tail calls materialize call target either in gtControlExpr or in gtCallAddr.
4943         assert(target != nullptr);
4944
4945         genConsumeReg(target);
4946         genCopyRegIfNeeded(target, REG_RAX);
4947         return;
4948     }
4949
4950     // For a pinvoke to unmanged code we emit a label to clear
4951     // the GC pointer state before the callsite.
4952     // We can't utilize the typical lazy killing of GC pointers
4953     // at (or inside) the callsite.
4954     if (call->IsUnmanaged())
4955     {
4956         genDefineTempLabel(genCreateTempLabel());
4957     }
4958
4959     // Determine return value size(s).
4960     ReturnTypeDesc* retTypeDesc   = call->GetReturnTypeDesc();
4961     emitAttr        retSize       = EA_PTRSIZE;
4962     emitAttr        secondRetSize = EA_UNKNOWN;
4963
4964     if (call->HasMultiRegRetVal())
4965     {
4966         retSize       = emitTypeSize(retTypeDesc->GetReturnRegType(0));
4967         secondRetSize = emitTypeSize(retTypeDesc->GetReturnRegType(1));
4968     }
4969     else
4970     {
4971         assert(!varTypeIsStruct(call));
4972
4973         if (call->gtType == TYP_REF || call->gtType == TYP_ARRAY)
4974         {
4975             retSize = EA_GCREF;
4976         }
4977         else if (call->gtType == TYP_BYREF)
4978         {
4979             retSize = EA_BYREF;
4980         }
4981     }
4982
4983     bool            fPossibleSyncHelperCall = false;
4984     CorInfoHelpFunc helperNum               = CORINFO_HELP_UNDEF;
4985
4986     // We need to propagate the IL offset information to the call instruction, so we can emit
4987     // an IL to native mapping record for the call, to support managed return value debugging.
4988     // We don't want tail call helper calls that were converted from normal calls to get a record,
4989     // so we skip this hash table lookup logic in that case.
4990     if (compiler->opts.compDbgInfo && compiler->genCallSite2ILOffsetMap != nullptr && !call->IsTailCall())
4991     {
4992         (void)compiler->genCallSite2ILOffsetMap->Lookup(call, &ilOffset);
4993     }
4994
4995 #if defined(_TARGET_X86_)
4996     bool fCallerPop = call->CallerPop();
4997
4998 #ifdef UNIX_X86_ABI
4999     if (!call->IsUnmanaged())
5000     {
5001         CorInfoCallConv callConv = CORINFO_CALLCONV_DEFAULT;
5002
5003         if ((callType != CT_HELPER) && call->callSig)
5004         {
5005             callConv = call->callSig->callConv;
5006         }
5007
5008         fCallerPop |= IsCallerPop(callConv);
5009     }
5010 #endif // UNIX_X86_ABI
5011
5012     // If the callee pops the arguments, we pass a positive value as the argSize, and the emitter will
5013     // adjust its stack level accordingly.
5014     // If the caller needs to explicitly pop its arguments, we must pass a negative value, and then do the
5015     // pop when we're done.
5016     ssize_t argSizeForEmitter = stackArgBytes;
5017     if (fCallerPop)
5018     {
5019         argSizeForEmitter = -stackArgBytes;
5020     }
5021 #endif // defined(_TARGET_X86_)
5022
5023 #ifdef FEATURE_AVX_SUPPORT
5024     // When it's a PInvoke call and the call type is USER function, we issue VZEROUPPER here
5025     // if the function contains 256bit AVX instructions, this is to avoid AVX-256 to Legacy SSE
5026     // transition penalty, assuming the user function contains legacy SSE instruction.
5027     // To limit code size increase impact: we only issue VZEROUPPER before PInvoke call, not issue
5028     // VZEROUPPER after PInvoke call because transition penalty from legacy SSE to AVX only happens
5029     // when there's preceding 256-bit AVX to legacy SSE transition penalty.
5030     if (call->IsPInvoke() && (call->gtCallType == CT_USER_FUNC) && getEmitter()->Contains256bitAVX())
5031     {
5032         assert(compiler->getSIMDInstructionSet() == InstructionSet_AVX);
5033         instGen(INS_vzeroupper);
5034     }
5035 #endif
5036
5037     if (target != nullptr)
5038     {
5039 #ifdef _TARGET_X86_
5040         if (call->IsVirtualStub() && (call->gtCallType == CT_INDIRECT))
5041         {
5042             // On x86, we need to generate a very specific pattern for indirect VSD calls:
5043             //
5044             //    3-byte nop
5045             //    call dword ptr [eax]
5046             //
5047             // Where EAX is also used as an argument to the stub dispatch helper. Make
5048             // sure that the call target address is computed into EAX in this case.
5049
5050             assert(REG_VIRTUAL_STUB_PARAM == REG_VIRTUAL_STUB_TARGET);
5051
5052             assert(target->isContainedIndir());
5053             assert(target->OperGet() == GT_IND);
5054
5055             GenTree* addr = target->AsIndir()->Addr();
5056             assert(addr->isUsedFromReg());
5057
5058             genConsumeReg(addr);
5059             genCopyRegIfNeeded(addr, REG_VIRTUAL_STUB_TARGET);
5060
5061             getEmitter()->emitIns_Nop(3);
5062
5063             // clang-format off
5064             getEmitter()->emitIns_Call(emitter::EmitCallType(emitter::EC_INDIR_ARD),
5065                                        methHnd,
5066                                        INDEBUG_LDISASM_COMMA(sigInfo)
5067                                        nullptr,
5068                                        argSizeForEmitter,
5069                                        retSize
5070                                        MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(secondRetSize),
5071                                        gcInfo.gcVarPtrSetCur,
5072                                        gcInfo.gcRegGCrefSetCur,
5073                                        gcInfo.gcRegByrefSetCur,
5074                                        ilOffset, REG_VIRTUAL_STUB_TARGET, REG_NA, 1, 0);
5075             // clang-format on
5076         }
5077         else
5078 #endif
5079             if (target->isContainedIndir())
5080         {
5081             if (target->AsIndir()->HasBase() && target->AsIndir()->Base()->isContainedIntOrIImmed())
5082             {
5083                 // Note that if gtControlExpr is an indir of an absolute address, we mark it as
5084                 // contained only if it can be encoded as PC-relative offset.
5085                 assert(target->AsIndir()->Base()->AsIntConCommon()->FitsInAddrBase(compiler));
5086
5087                 // clang-format off
5088                 genEmitCall(emitter::EC_FUNC_TOKEN_INDIR,
5089                             methHnd,
5090                             INDEBUG_LDISASM_COMMA(sigInfo)
5091                             (void*) target->AsIndir()->Base()->AsIntConCommon()->IconValue()
5092                             X86_ARG(argSizeForEmitter),
5093                             retSize
5094                             MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(secondRetSize),
5095                             ilOffset);
5096                 // clang-format on
5097             }
5098             else
5099             {
5100                 // clang-format off
5101                 genEmitCall(emitter::EC_INDIR_ARD,
5102                             methHnd,
5103                             INDEBUG_LDISASM_COMMA(sigInfo)
5104                             target->AsIndir()
5105                             X86_ARG(argSizeForEmitter),
5106                             retSize
5107                             MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(secondRetSize),
5108                             ilOffset);
5109                 // clang-format on
5110             }
5111         }
5112         else
5113         {
5114             // We have already generated code for gtControlExpr evaluating it into a register.
5115             // We just need to emit "call reg" in this case.
5116             assert(genIsValidIntReg(target->gtRegNum));
5117
5118             // clang-format off
5119             genEmitCall(emitter::EC_INDIR_R,
5120                         methHnd,
5121                         INDEBUG_LDISASM_COMMA(sigInfo)
5122                         nullptr // addr
5123                         X86_ARG(argSizeForEmitter),
5124                         retSize
5125                         MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(secondRetSize),
5126                         ilOffset,
5127                         genConsumeReg(target));
5128             // clang-format on
5129         }
5130     }
5131 #ifdef FEATURE_READYTORUN_COMPILER
5132     else if (call->gtEntryPoint.addr != nullptr)
5133     {
5134         // clang-format off
5135         genEmitCall((call->gtEntryPoint.accessType == IAT_VALUE) ? emitter::EC_FUNC_TOKEN
5136                                                                  : emitter::EC_FUNC_TOKEN_INDIR,
5137                     methHnd,
5138                     INDEBUG_LDISASM_COMMA(sigInfo)
5139                     (void*) call->gtEntryPoint.addr
5140                     X86_ARG(argSizeForEmitter),
5141                     retSize
5142                     MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(secondRetSize),
5143                     ilOffset);
5144         // clang-format on
5145     }
5146 #endif
5147     else
5148     {
5149         // Generate a direct call to a non-virtual user defined or helper method
5150         assert(callType == CT_HELPER || callType == CT_USER_FUNC);
5151
5152         void* addr = nullptr;
5153         if (callType == CT_HELPER)
5154         {
5155             // Direct call to a helper method.
5156             helperNum = compiler->eeGetHelperNum(methHnd);
5157             noway_assert(helperNum != CORINFO_HELP_UNDEF);
5158
5159             void* pAddr = nullptr;
5160             addr        = compiler->compGetHelperFtn(helperNum, (void**)&pAddr);
5161
5162             if (addr == nullptr)
5163             {
5164                 addr = pAddr;
5165             }
5166
5167             // tracking of region protected by the monitor in synchronized methods
5168             if (compiler->info.compFlags & CORINFO_FLG_SYNCH)
5169             {
5170                 fPossibleSyncHelperCall = true;
5171             }
5172         }
5173         else
5174         {
5175             // Direct call to a non-virtual user function.
5176             addr = call->gtDirectCallAddress;
5177         }
5178
5179         // Non-virtual direct calls to known addresses
5180
5181         // clang-format off
5182         genEmitCall(emitter::EC_FUNC_TOKEN,
5183                     methHnd,
5184                     INDEBUG_LDISASM_COMMA(sigInfo)
5185                     addr
5186                     X86_ARG(argSizeForEmitter),
5187                     retSize
5188                     MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(secondRetSize),
5189                     ilOffset);
5190         // clang-format on
5191     }
5192
5193     // if it was a pinvoke we may have needed to get the address of a label
5194     if (genPendingCallLabel)
5195     {
5196         assert(call->IsUnmanaged());
5197         genDefineTempLabel(genPendingCallLabel);
5198         genPendingCallLabel = nullptr;
5199     }
5200
5201     // Update GC info:
5202     // All Callee arg registers are trashed and no longer contain any GC pointers.
5203     // TODO-XArch-Bug?: As a matter of fact shouldn't we be killing all of callee trashed regs here?
5204     // For now we will assert that other than arg regs gc ref/byref set doesn't contain any other
5205     // registers from RBM_CALLEE_TRASH.
5206     assert((gcInfo.gcRegGCrefSetCur & (RBM_CALLEE_TRASH & ~RBM_ARG_REGS)) == 0);
5207     assert((gcInfo.gcRegByrefSetCur & (RBM_CALLEE_TRASH & ~RBM_ARG_REGS)) == 0);
5208     gcInfo.gcRegGCrefSetCur &= ~RBM_ARG_REGS;
5209     gcInfo.gcRegByrefSetCur &= ~RBM_ARG_REGS;
5210
5211     var_types returnType = call->TypeGet();
5212     if (returnType != TYP_VOID)
5213     {
5214 #ifdef _TARGET_X86_
5215         if (varTypeIsFloating(returnType))
5216         {
5217             // Spill the value from the fp stack.
5218             // Then, load it into the target register.
5219             call->gtFlags |= GTF_SPILL;
5220             regSet.rsSpillFPStack(call);
5221             call->gtFlags |= GTF_SPILLED;
5222             call->gtFlags &= ~GTF_SPILL;
5223         }
5224         else
5225 #endif // _TARGET_X86_
5226         {
5227             regNumber returnReg;
5228
5229             if (call->HasMultiRegRetVal())
5230             {
5231                 assert(retTypeDesc != nullptr);
5232                 unsigned regCount = retTypeDesc->GetReturnRegCount();
5233
5234                 // If regs allocated to call node are different from ABI return
5235                 // regs in which the call has returned its result, move the result
5236                 // to regs allocated to call node.
5237                 for (unsigned i = 0; i < regCount; ++i)
5238                 {
5239                     var_types regType      = retTypeDesc->GetReturnRegType(i);
5240                     returnReg              = retTypeDesc->GetABIReturnReg(i);
5241                     regNumber allocatedReg = call->GetRegNumByIdx(i);
5242                     if (returnReg != allocatedReg)
5243                     {
5244                         inst_RV_RV(ins_Copy(regType), allocatedReg, returnReg, regType);
5245                     }
5246                 }
5247
5248 #ifdef FEATURE_SIMD
5249                 // A Vector3 return value is stored in xmm0 and xmm1.
5250                 // RyuJIT assumes that the upper unused bits of xmm1 are cleared but
5251                 // the native compiler doesn't guarantee it.
5252                 if (returnType == TYP_SIMD12)
5253                 {
5254                     returnReg = retTypeDesc->GetABIReturnReg(1);
5255                     // Clear the upper 32 bits by two shift instructions.
5256                     // retReg = retReg << 96
5257                     // retReg = retReg >> 96
5258                     getEmitter()->emitIns_R_I(INS_pslldq, emitActualTypeSize(TYP_SIMD12), returnReg, 12);
5259                     getEmitter()->emitIns_R_I(INS_psrldq, emitActualTypeSize(TYP_SIMD12), returnReg, 12);
5260                 }
5261 #endif // FEATURE_SIMD
5262             }
5263             else
5264             {
5265 #ifdef _TARGET_X86_
5266                 if (call->IsHelperCall(compiler, CORINFO_HELP_INIT_PINVOKE_FRAME))
5267                 {
5268                     // The x86 CORINFO_HELP_INIT_PINVOKE_FRAME helper uses a custom calling convention that returns with
5269                     // TCB in REG_PINVOKE_TCB. AMD64/ARM64 use the standard calling convention. fgMorphCall() sets the
5270                     // correct argument registers.
5271                     returnReg = REG_PINVOKE_TCB;
5272                 }
5273                 else
5274 #endif // _TARGET_X86_
5275                     if (varTypeIsFloating(returnType))
5276                 {
5277                     returnReg = REG_FLOATRET;
5278                 }
5279                 else
5280                 {
5281                     returnReg = REG_INTRET;
5282                 }
5283
5284                 if (call->gtRegNum != returnReg)
5285                 {
5286                     inst_RV_RV(ins_Copy(returnType), call->gtRegNum, returnReg, returnType);
5287                 }
5288             }
5289
5290             genProduceReg(call);
5291         }
5292     }
5293
5294     // If there is nothing next, that means the result is thrown away, so this value is not live.
5295     // However, for minopts or debuggable code, we keep it live to support managed return value debugging.
5296     if ((call->gtNext == nullptr) && !compiler->opts.MinOpts() && !compiler->opts.compDbgCode)
5297     {
5298         gcInfo.gcMarkRegSetNpt(RBM_INTRET);
5299     }
5300
5301 #if !FEATURE_EH_FUNCLETS
5302     //-------------------------------------------------------------------------
5303     // Create a label for tracking of region protected by the monitor in synchronized methods.
5304     // This needs to be here, rather than above where fPossibleSyncHelperCall is set,
5305     // so the GC state vars have been updated before creating the label.
5306
5307     if (fPossibleSyncHelperCall)
5308     {
5309         switch (helperNum)
5310         {
5311             case CORINFO_HELP_MON_ENTER:
5312             case CORINFO_HELP_MON_ENTER_STATIC:
5313                 noway_assert(compiler->syncStartEmitCookie == NULL);
5314                 compiler->syncStartEmitCookie =
5315                     getEmitter()->emitAddLabel(gcInfo.gcVarPtrSetCur, gcInfo.gcRegGCrefSetCur, gcInfo.gcRegByrefSetCur);
5316                 noway_assert(compiler->syncStartEmitCookie != NULL);
5317                 break;
5318             case CORINFO_HELP_MON_EXIT:
5319             case CORINFO_HELP_MON_EXIT_STATIC:
5320                 noway_assert(compiler->syncEndEmitCookie == NULL);
5321                 compiler->syncEndEmitCookie =
5322                     getEmitter()->emitAddLabel(gcInfo.gcVarPtrSetCur, gcInfo.gcRegGCrefSetCur, gcInfo.gcRegByrefSetCur);
5323                 noway_assert(compiler->syncEndEmitCookie != NULL);
5324                 break;
5325             default:
5326                 break;
5327         }
5328     }
5329 #endif // !FEATURE_EH_FUNCLETS
5330
5331     unsigned stackAdjustBias = 0;
5332
5333 #if defined(_TARGET_X86_)
5334     // Is the caller supposed to pop the arguments?
5335     if (fCallerPop && (stackArgBytes != 0))
5336     {
5337         stackAdjustBias = stackArgBytes;
5338     }
5339
5340     SubtractStackLevel(stackArgBytes);
5341 #endif // _TARGET_X86_
5342
5343     genRemoveAlignmentAfterCall(call, stackAdjustBias);
5344 }
5345
5346 // Produce code for a GT_JMP node.
5347 // The arguments of the caller needs to be transferred to the callee before exiting caller.
5348 // The actual jump to callee is generated as part of caller epilog sequence.
5349 // Therefore the codegen of GT_JMP is to ensure that the callee arguments are correctly setup.
5350 void CodeGen::genJmpMethod(GenTreePtr jmp)
5351 {
5352     assert(jmp->OperGet() == GT_JMP);
5353     assert(compiler->compJmpOpUsed);
5354
5355     // If no arguments, nothing to do
5356     if (compiler->info.compArgsCount == 0)
5357     {
5358         return;
5359     }
5360
5361     // Make sure register arguments are in their initial registers
5362     // and stack arguments are put back as well.
5363     unsigned   varNum;
5364     LclVarDsc* varDsc;
5365
5366     // First move any en-registered stack arguments back to the stack.
5367     // At the same time any reg arg not in correct reg is moved back to its stack location.
5368     //
5369     // We are not strictly required to spill reg args that are not in the desired reg for a jmp call
5370     // But that would require us to deal with circularity while moving values around.  Spilling
5371     // to stack makes the implementation simple, which is not a bad trade off given Jmp calls
5372     // are not frequent.
5373     for (varNum = 0; (varNum < compiler->info.compArgsCount); varNum++)
5374     {
5375         varDsc = compiler->lvaTable + varNum;
5376
5377         if (varDsc->lvPromoted)
5378         {
5379             noway_assert(varDsc->lvFieldCnt == 1); // We only handle one field here
5380
5381             unsigned fieldVarNum = varDsc->lvFieldLclStart;
5382             varDsc               = compiler->lvaTable + fieldVarNum;
5383         }
5384         noway_assert(varDsc->lvIsParam);
5385
5386         if (varDsc->lvIsRegArg && (varDsc->lvRegNum != REG_STK))
5387         {
5388             // Skip reg args which are already in its right register for jmp call.
5389             // If not, we will spill such args to their stack locations.
5390             //
5391             // If we need to generate a tail call profiler hook, then spill all
5392             // arg regs to free them up for the callback.
5393             if (!compiler->compIsProfilerHookNeeded() && (varDsc->lvRegNum == varDsc->lvArgReg))
5394             {
5395                 continue;
5396             }
5397         }
5398         else if (varDsc->lvRegNum == REG_STK)
5399         {
5400             // Skip args which are currently living in stack.
5401             continue;
5402         }
5403
5404         // If we came here it means either a reg argument not in the right register or
5405         // a stack argument currently living in a register.  In either case the following
5406         // assert should hold.
5407         assert(varDsc->lvRegNum != REG_STK);
5408
5409         var_types loadType = varDsc->lvaArgType();
5410         getEmitter()->emitIns_S_R(ins_Store(loadType), emitTypeSize(loadType), varDsc->lvRegNum, varNum, 0);
5411
5412         // Update lvRegNum life and GC info to indicate lvRegNum is dead and varDsc stack slot is going live.
5413         // Note that we cannot modify varDsc->lvRegNum here because another basic block may not be expecting it.
5414         // Therefore manually update life of varDsc->lvRegNum.
5415         regMaskTP tempMask = varDsc->lvRegMask();
5416         regSet.RemoveMaskVars(tempMask);
5417         gcInfo.gcMarkRegSetNpt(tempMask);
5418         if (compiler->lvaIsGCTracked(varDsc))
5419         {
5420 #ifdef DEBUG
5421             if (!VarSetOps::IsMember(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex))
5422             {
5423                 JITDUMP("\t\t\t\t\t\t\tVar V%02u becoming live\n", varNum);
5424             }
5425             else
5426             {
5427                 JITDUMP("\t\t\t\t\t\t\tVar V%02u continuing live\n", varNum);
5428             }
5429 #endif // DEBUG
5430
5431             VarSetOps::AddElemD(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex);
5432         }
5433     }
5434
5435 #ifdef PROFILING_SUPPORTED
5436     // At this point all arg regs are free.
5437     // Emit tail call profiler callback.
5438     genProfilingLeaveCallback(CORINFO_HELP_PROF_FCN_TAILCALL);
5439 #endif
5440
5441     // Next move any un-enregistered register arguments back to their register.
5442     regMaskTP fixedIntArgMask = RBM_NONE;    // tracks the int arg regs occupying fixed args in case of a vararg method.
5443     unsigned  firstArgVarNum  = BAD_VAR_NUM; // varNum of the first argument in case of a vararg method.
5444     for (varNum = 0; (varNum < compiler->info.compArgsCount); varNum++)
5445     {
5446         varDsc = compiler->lvaTable + varNum;
5447         if (varDsc->lvPromoted)
5448         {
5449             noway_assert(varDsc->lvFieldCnt == 1); // We only handle one field here
5450
5451             unsigned fieldVarNum = varDsc->lvFieldLclStart;
5452             varDsc               = compiler->lvaTable + fieldVarNum;
5453         }
5454         noway_assert(varDsc->lvIsParam);
5455
5456         // Skip if arg not passed in a register.
5457         if (!varDsc->lvIsRegArg)
5458         {
5459             continue;
5460         }
5461
5462 #if defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
5463         if (varTypeIsStruct(varDsc))
5464         {
5465             CORINFO_CLASS_HANDLE typeHnd = varDsc->lvVerTypeInfo.GetClassHandle();
5466             assert(typeHnd != nullptr);
5467
5468             SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR structDesc;
5469             compiler->eeGetSystemVAmd64PassStructInRegisterDescriptor(typeHnd, &structDesc);
5470             assert(structDesc.passedInRegisters);
5471
5472             unsigned __int8 offset0 = 0;
5473             unsigned __int8 offset1 = 0;
5474             var_types       type0   = TYP_UNKNOWN;
5475             var_types       type1   = TYP_UNKNOWN;
5476
5477             // Get the eightbyte data
5478             compiler->GetStructTypeOffset(structDesc, &type0, &type1, &offset0, &offset1);
5479
5480             // Move the values into the right registers.
5481             //
5482
5483             // Update varDsc->lvArgReg and lvOtherArgReg life and GC Info to indicate varDsc stack slot is dead and
5484             // argReg is going live. Note that we cannot modify varDsc->lvRegNum and lvOtherArgReg here because another
5485             // basic block may not be expecting it. Therefore manually update life of argReg.  Note that GT_JMP marks
5486             // the end of the basic block and after which reg life and gc info will be recomputed for the new block in
5487             // genCodeForBBList().
5488             if (type0 != TYP_UNKNOWN)
5489             {
5490                 getEmitter()->emitIns_R_S(ins_Load(type0), emitTypeSize(type0), varDsc->lvArgReg, varNum, offset0);
5491                 regSet.rsMaskVars |= genRegMask(varDsc->lvArgReg);
5492                 gcInfo.gcMarkRegPtrVal(varDsc->lvArgReg, type0);
5493             }
5494
5495             if (type1 != TYP_UNKNOWN)
5496             {
5497                 getEmitter()->emitIns_R_S(ins_Load(type1), emitTypeSize(type1), varDsc->lvOtherArgReg, varNum, offset1);
5498                 regSet.rsMaskVars |= genRegMask(varDsc->lvOtherArgReg);
5499                 gcInfo.gcMarkRegPtrVal(varDsc->lvOtherArgReg, type1);
5500             }
5501
5502             if (varDsc->lvTracked)
5503             {
5504                 VarSetOps::RemoveElemD(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex);
5505             }
5506         }
5507         else
5508 #endif // !defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
5509         {
5510             // Register argument
5511             noway_assert(isRegParamType(genActualType(varDsc->TypeGet())));
5512
5513             // Is register argument already in the right register?
5514             // If not load it from its stack location.
5515             var_types loadType = varDsc->lvaArgType();
5516             regNumber argReg   = varDsc->lvArgReg; // incoming arg register
5517
5518             if (varDsc->lvRegNum != argReg)
5519             {
5520                 assert(genIsValidReg(argReg));
5521                 getEmitter()->emitIns_R_S(ins_Load(loadType), emitTypeSize(loadType), argReg, varNum, 0);
5522
5523                 // Update argReg life and GC Info to indicate varDsc stack slot is dead and argReg is going live.
5524                 // Note that we cannot modify varDsc->lvRegNum here because another basic block may not be expecting it.
5525                 // Therefore manually update life of argReg.  Note that GT_JMP marks the end of the basic block
5526                 // and after which reg life and gc info will be recomputed for the new block in genCodeForBBList().
5527                 regSet.AddMaskVars(genRegMask(argReg));
5528                 gcInfo.gcMarkRegPtrVal(argReg, loadType);
5529                 if (compiler->lvaIsGCTracked(varDsc))
5530                 {
5531 #ifdef DEBUG
5532                     if (VarSetOps::IsMember(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex))
5533                     {
5534                         JITDUMP("\t\t\t\t\t\t\tVar V%02u becoming dead\n", varNum);
5535                     }
5536                     else
5537                     {
5538                         JITDUMP("\t\t\t\t\t\t\tVar V%02u continuing dead\n", varNum);
5539                     }
5540 #endif // DEBUG
5541
5542                     VarSetOps::RemoveElemD(compiler, gcInfo.gcVarPtrSetCur, varDsc->lvVarIndex);
5543                 }
5544             }
5545         }
5546
5547 #if FEATURE_VARARG && defined(_TARGET_AMD64_)
5548         // In case of a jmp call to a vararg method also pass the float/double arg in the corresponding int arg
5549         // register. This is due to the AMD64 ABI which requires floating point values passed to varargs functions to
5550         // be passed in both integer and floating point registers. It doesn't apply to x86, which passes floating point
5551         // values on the stack.
5552         if (compiler->info.compIsVarArgs)
5553         {
5554             regNumber intArgReg;
5555             var_types loadType = varDsc->lvaArgType();
5556             regNumber argReg   = varDsc->lvArgReg; // incoming arg register
5557
5558             if (varTypeIsFloating(loadType))
5559             {
5560                 intArgReg       = compiler->getCallArgIntRegister(argReg);
5561                 instruction ins = ins_CopyFloatToInt(loadType, TYP_LONG);
5562                 inst_RV_RV(ins, argReg, intArgReg, loadType);
5563             }
5564             else
5565             {
5566                 intArgReg = argReg;
5567             }
5568
5569             fixedIntArgMask |= genRegMask(intArgReg);
5570
5571             if (intArgReg == REG_ARG_0)
5572             {
5573                 assert(firstArgVarNum == BAD_VAR_NUM);
5574                 firstArgVarNum = varNum;
5575             }
5576         }
5577 #endif // FEATURE_VARARG
5578     }
5579
5580 #if FEATURE_VARARG && defined(_TARGET_AMD64_)
5581     // Jmp call to a vararg method - if the method has fewer than 4 fixed arguments,
5582     // load the remaining arg registers (both int and float) from the corresponding
5583     // shadow stack slots.  This is for the reason that we don't know the number and type
5584     // of non-fixed params passed by the caller, therefore we have to assume the worst case
5585     // of caller passing float/double args both in int and float arg regs.
5586     //
5587     // This doesn't apply to x86, which doesn't pass floating point values in floating
5588     // point registers.
5589     //
5590     // The caller could have passed gc-ref/byref type var args.  Since these are var args
5591     // the callee no way of knowing their gc-ness.  Therefore, mark the region that loads
5592     // remaining arg registers from shadow stack slots as non-gc interruptible.
5593     if (fixedIntArgMask != RBM_NONE)
5594     {
5595         assert(compiler->info.compIsVarArgs);
5596         assert(firstArgVarNum != BAD_VAR_NUM);
5597
5598         regMaskTP remainingIntArgMask = RBM_ARG_REGS & ~fixedIntArgMask;
5599         if (remainingIntArgMask != RBM_NONE)
5600         {
5601             instruction insCopyIntToFloat = ins_CopyIntToFloat(TYP_LONG, TYP_DOUBLE);
5602             getEmitter()->emitDisableGC();
5603             for (int argNum = 0, argOffset = 0; argNum < MAX_REG_ARG; ++argNum)
5604             {
5605                 regNumber argReg     = intArgRegs[argNum];
5606                 regMaskTP argRegMask = genRegMask(argReg);
5607
5608                 if ((remainingIntArgMask & argRegMask) != 0)
5609                 {
5610                     remainingIntArgMask &= ~argRegMask;
5611                     getEmitter()->emitIns_R_S(INS_mov, EA_8BYTE, argReg, firstArgVarNum, argOffset);
5612
5613                     // also load it in corresponding float arg reg
5614                     regNumber floatReg = compiler->getCallArgFloatRegister(argReg);
5615                     inst_RV_RV(insCopyIntToFloat, floatReg, argReg);
5616                 }
5617
5618                 argOffset += REGSIZE_BYTES;
5619             }
5620             getEmitter()->emitEnableGC();
5621         }
5622     }
5623 #endif // FEATURE_VARARG
5624 }
5625
5626 // produce code for a GT_LEA subnode
5627 void CodeGen::genLeaInstruction(GenTreeAddrMode* lea)
5628 {
5629     emitAttr size = emitTypeSize(lea);
5630     genConsumeOperands(lea);
5631
5632     if (lea->Base() && lea->Index())
5633     {
5634         regNumber baseReg  = lea->Base()->gtRegNum;
5635         regNumber indexReg = lea->Index()->gtRegNum;
5636         getEmitter()->emitIns_R_ARX(INS_lea, size, lea->gtRegNum, baseReg, indexReg, lea->gtScale, lea->gtOffset);
5637     }
5638     else if (lea->Base())
5639     {
5640         getEmitter()->emitIns_R_AR(INS_lea, size, lea->gtRegNum, lea->Base()->gtRegNum, lea->gtOffset);
5641     }
5642     else if (lea->Index())
5643     {
5644         getEmitter()->emitIns_R_ARX(INS_lea, size, lea->gtRegNum, REG_NA, lea->Index()->gtRegNum, lea->gtScale,
5645                                     lea->gtOffset);
5646     }
5647
5648     genProduceReg(lea);
5649 }
5650
5651 //-------------------------------------------------------------------------------------------
5652 // genJumpKindsForTree:  Determine the number and kinds of conditional branches
5653 //                       necessary to implement the given GT_CMP node
5654 //
5655 // Arguments:
5656 //    cmpTree          - (input) The GenTree node that is used to set the Condition codes
5657 //                     - The GenTree Relop node that was used to set the Condition codes
5658 //   jmpKind[2]        - (output) One or two conditional branch instructions
5659 //   jmpToTrueLabel[2] - (output) When true we branch to the true case
5660 //                       When false we create a second label and branch to the false case
5661 //                       Only GT_EQ for a floating point compares can have a false value.
5662 //
5663 // Return Value:
5664 //    Sets the proper values into the array elements of jmpKind[] and jmpToTrueLabel[]
5665 //
5666 // Assumptions:
5667 //    At least one conditional branch instruction will be returned.
5668 //    Typically only one conditional branch is needed
5669 //     and the second jmpKind[] value is set to EJ_NONE
5670 //
5671 // Notes:
5672 //    jmpToTrueLabel[i]= true  implies branch when the compare operation is true.
5673 //    jmpToTrueLabel[i]= false implies branch when the compare operation is false.
5674 //-------------------------------------------------------------------------------------------
5675
5676 // static
5677 void CodeGen::genJumpKindsForTree(GenTreePtr cmpTree, emitJumpKind jmpKind[2], bool jmpToTrueLabel[2])
5678 {
5679     // Except for BEQ (=  ordered GT_EQ) both jumps are to the true label.
5680     jmpToTrueLabel[0] = true;
5681     jmpToTrueLabel[1] = true;
5682
5683     // For integer comparisons just use genJumpKindForOper
5684     if (!varTypeIsFloating(cmpTree->gtOp.gtOp1->gtEffectiveVal()))
5685     {
5686         CompareKind compareKind = ((cmpTree->gtFlags & GTF_UNSIGNED) != 0) ? CK_UNSIGNED : CK_SIGNED;
5687         jmpKind[0]              = genJumpKindForOper(cmpTree->gtOper, compareKind);
5688         jmpKind[1]              = EJ_NONE;
5689     }
5690     else
5691     {
5692         assert(cmpTree->OperIsCompare());
5693
5694         // For details on how we arrived at this mapping, see the comment block in genCodeForTreeNode()
5695         // while generating code for compare opererators (e.g. GT_EQ etc).
5696         if ((cmpTree->gtFlags & GTF_RELOP_NAN_UN) != 0)
5697         {
5698             // Must branch if we have an NaN, unordered
5699             switch (cmpTree->gtOper)
5700             {
5701                 case GT_LT:
5702                 case GT_GT:
5703                     jmpKind[0] = EJ_jb;
5704                     jmpKind[1] = EJ_NONE;
5705                     break;
5706
5707                 case GT_LE:
5708                 case GT_GE:
5709                     jmpKind[0] = EJ_jbe;
5710                     jmpKind[1] = EJ_NONE;
5711                     break;
5712
5713                 case GT_NE:
5714                     jmpKind[0] = EJ_jpe;
5715                     jmpKind[1] = EJ_jne;
5716                     break;
5717
5718                 case GT_EQ:
5719                     jmpKind[0] = EJ_je;
5720                     jmpKind[1] = EJ_NONE;
5721                     break;
5722
5723                 default:
5724                     unreached();
5725             }
5726         }
5727         else // ((cmpTree->gtFlags & GTF_RELOP_NAN_UN) == 0)
5728         {
5729             // Do not branch if we have an NaN, unordered
5730             switch (cmpTree->gtOper)
5731             {
5732                 case GT_LT:
5733                 case GT_GT:
5734                     jmpKind[0] = EJ_ja;
5735                     jmpKind[1] = EJ_NONE;
5736                     break;
5737
5738                 case GT_LE:
5739                 case GT_GE:
5740                     jmpKind[0] = EJ_jae;
5741                     jmpKind[1] = EJ_NONE;
5742                     break;
5743
5744                 case GT_NE:
5745                     jmpKind[0] = EJ_jne;
5746                     jmpKind[1] = EJ_NONE;
5747                     break;
5748
5749                 case GT_EQ:
5750                     jmpKind[0]        = EJ_jpe;
5751                     jmpKind[1]        = EJ_je;
5752                     jmpToTrueLabel[0] = false;
5753                     break;
5754
5755                 default:
5756                     unreached();
5757             }
5758         }
5759     }
5760 }
5761
5762 #if !defined(_TARGET_64BIT_)
5763 //------------------------------------------------------------------------
5764 // genJumpKindsForTreeLongHi: Generate the jump types for compare
5765 // operators of the high parts of a compare with long type operands
5766 // on x86 for the case where rel-op result needs to be materialized into a
5767 // register.
5768 //
5769 // Arguments:
5770 //    cmpTree - The GT_CMP node
5771 //    jmpKind - Return array of jump kinds
5772 //    jmpToTrueLabel - Return array of if the jump is going to true label
5773 //
5774 // Return Value:
5775 //    None.
5776 //
5777 void CodeGen::genJumpKindsForTreeLongHi(GenTreePtr cmpTree, emitJumpKind jmpKind[2])
5778 {
5779     assert(cmpTree->OperIsCompare());
5780     CompareKind compareKind = ((cmpTree->gtFlags & GTF_UNSIGNED) != 0) ? CK_UNSIGNED : CK_SIGNED;
5781
5782     switch (cmpTree->gtOper)
5783     {
5784         case GT_LT:
5785         case GT_LE:
5786             if (compareKind == CK_SIGNED)
5787             {
5788                 jmpKind[0] = EJ_jl;
5789                 jmpKind[1] = EJ_jg;
5790             }
5791             else
5792             {
5793                 jmpKind[0] = EJ_jb;
5794                 jmpKind[1] = EJ_ja;
5795             }
5796             break;
5797
5798         case GT_GT:
5799         case GT_GE:
5800             if (compareKind == CK_SIGNED)
5801             {
5802                 jmpKind[0] = EJ_jg;
5803                 jmpKind[1] = EJ_jl;
5804             }
5805             else
5806             {
5807                 jmpKind[0] = EJ_ja;
5808                 jmpKind[1] = EJ_jb;
5809             }
5810             break;
5811
5812         case GT_EQ:
5813             // GT_EQ will not jump to the true label if the hi parts are equal
5814             jmpKind[0] = EJ_NONE;
5815             jmpKind[1] = EJ_jne;
5816             break;
5817
5818         case GT_NE:
5819             // GT_NE will always jump to the true label if the high parts are not equal
5820             jmpKind[0] = EJ_jne;
5821             jmpKind[1] = EJ_NONE;
5822             break;
5823
5824         default:
5825             unreached();
5826     }
5827 }
5828
5829 //------------------------------------------------------------------------
5830 // genCompareLong: Generate code for comparing two longs on x86 when the result of the compare
5831 // is manifested in a register.
5832 //
5833 // Arguments:
5834 //    treeNode - the compare tree
5835 //
5836 // Return Value:
5837 //    None.
5838 // Comments:
5839 // For long compares, we need to compare the high parts of operands first, then the low parts.
5840 // If the high compare is false, we do not need to compare the low parts. For less than and
5841 // greater than, if the high compare is true, we can assume the entire compare is true. For
5842 // compares that are realized in a register, we will generate:
5843 //
5844 //    Opcode            x86 equivalent          Comment
5845 //    ------            --------------          -------
5846 //    GT_EQ             cmp hiOp1,hiOp2         If any part is not equal, the entire compare
5847 //                      jne label               is false.
5848 //                      cmp loOp1,loOp2
5849 //                      label: sete
5850 //
5851 //    GT_NE             cmp hiOp1,hiOp2         If any part is not equal, the entire compare
5852 //                      jne label               is true.
5853 //                      cmp loOp1,loOp2
5854 //                      label: setne
5855 //
5856 //    GT_LT; unsigned   cmp hiOp1,hiOp2         If hiOp1 is not equal to hiOp2, the flags are set
5857 //                      jne label               correctly and we do not need to check lo. Otherwise,
5858 //                      cmp loOp1,loOp2         we need to compare the lo halves
5859 //                      label: setb
5860 //
5861 //    GT_LE; unsigned   cmp hiOp1,hiOp2         If hiOp1 is not equal to hiOp2, the flags are set
5862 //                      jne label               correctly and we do not need to check lo. Otherwise,
5863 //                      cmp loOp1,loOp2         we need to compare the lo halves
5864 //                      label: setbe
5865 //
5866 //    GT_GT; unsigned   cmp hiOp1,hiOp2         If hiOp1 is not equal to hiOp2, the flags are set
5867 //                      jne label               correctly and we do not need to check lo. Otherwise,
5868 //                      cmp loOp1,loOp2         we need to compare the lo halves
5869 //                      label: seta
5870 //
5871 //    GT_GE; unsigned   cmp hiOp1,hiOp2         If hiOp1 is not equal to hiOp2, the flags are set
5872 //                      jne label               correctly and we do not need to check lo. Otherwise,
5873 //                      cmp loOp1,loOp2         we need to compare the lo halves
5874 //                      label: setae
5875 //
5876 // For signed long comparisons, we need additional labels, as we need to use signed conditions on the
5877 // "set" instruction:
5878 //
5879 //    GT_LT; signed     cmp hiOp1,hiOp2         If hiOp1 is not equal to hiOp2, the flags are set
5880 //                      jne labelHi             correctly and we do not need to check lo. Otherwise,
5881 //                      cmp loOp1,loOp2         we need to compare the lo halves
5882 //                      setb                    Unsigned set for lo compare
5883 //                      jmp labelFinal
5884 //                      labelHi: setl           Signed set for high compare
5885 //                      labelFinal:
5886 //
5887 //    GT_LE; signed     cmp hiOp1,hiOp2         If hiOp1 is not equal to hiOp2, the flags are set
5888 //                      jne labelHi             correctly and we do not need to check lo. Otherwise,
5889 //                      cmp loOp1,loOp2         we need to compare the lo halves
5890 //                      setbe                   Unsigend set for lo compare
5891 //                      jmp labelFinal
5892 //                      labelHi: setle          Signed set for hi compare
5893 //                      labelFinal:
5894 //
5895 //    GT_GT; signed     cmp hiOp1,hiOp2         If hiOp1 is not equal to hiOp2, the flags are set
5896 //                      jne labelHi             correctly and we do not need to check lo. Otherwise,
5897 //                      cmp loOp1,loOp2         we need to compare the lo halves
5898 //                      seta                    Unsigned set for lo compare
5899 //                      jmp labelFinal
5900 //                      labelHi: setg           Signed set for high compare
5901 //                      labelFinal
5902 //
5903 //    GT_GE; signed     cmp hiOp1,hiOp2         If hiOp1 is not equal to hiOp2, the flags are set
5904 //                      jne labelHi             correctly and we do not need to check lo. Otherwise,
5905 //                      cmp loOp1,loOp2         we need to compare the lo halves
5906 //                      setae                   Unsigned set for lo compare
5907 //                      jmp labelFinal
5908 //                      labelHi: setge          Signed set for hi compare
5909 //                      labelFinal:
5910 //
5911 // TODO-X86-CQ: Check if hi or lo parts of op2 are 0 and change the compare to a test.
5912 void CodeGen::genCompareLong(GenTreePtr treeNode)
5913 {
5914     assert(treeNode->OperIsCompare());
5915
5916     GenTreeOp* tree = treeNode->AsOp();
5917     GenTreePtr op1  = tree->gtOp1;
5918     GenTreePtr op2  = tree->gtOp2;
5919
5920     assert(varTypeIsLong(op1->TypeGet()));
5921     assert(varTypeIsLong(op2->TypeGet()));
5922
5923     regNumber targetReg = treeNode->gtRegNum;
5924
5925     genConsumeOperands(tree);
5926
5927     GenTreePtr loOp1 = op1->gtGetOp1();
5928     GenTreePtr hiOp1 = op1->gtGetOp2();
5929     GenTreePtr loOp2 = op2->gtGetOp1();
5930     GenTreePtr hiOp2 = op2->gtGetOp2();
5931
5932     // Create compare for the high parts
5933     instruction ins     = INS_cmp;
5934     var_types   cmpType = TYP_INT;
5935     emitAttr    cmpAttr = emitTypeSize(cmpType);
5936
5937     // Emit the compare instruction
5938     getEmitter()->emitInsBinary(ins, cmpAttr, hiOp1, hiOp2);
5939
5940     // If the result is not being materialized in a register, we're done.
5941     if (targetReg == REG_NA)
5942     {
5943         return;
5944     }
5945
5946     // Generate the first jump for the high compare
5947     CompareKind compareKind = ((tree->gtFlags & GTF_UNSIGNED) != 0) ? CK_UNSIGNED : CK_SIGNED;
5948
5949     BasicBlock* labelHi    = genCreateTempLabel();
5950     BasicBlock* labelFinal = genCreateTempLabel();
5951
5952     if (compareKind == CK_SIGNED && (tree->gtOper != GT_NE && tree->gtOper != GT_EQ))
5953     {
5954         // If we are doing a signed comparison, we need to do a signed set if the high compare is true,
5955         // but an unsigned set if we fall through to the low compare. If we have a GT_NE or GT_EQ, we do not
5956         // need to worry about the sign of the comparison, so we can use the simplified case.
5957
5958         // We only have to check for equality for the hi comparison. If they are not equal, then the set will
5959         // do the right thing. If they are equal, we have to check the lo halves.
5960         inst_JMP(EJ_jne, labelHi);
5961
5962         // Emit the comparison. Perform the set for the lo. Jump to labelFinal
5963         getEmitter()->emitInsBinary(ins, cmpAttr, loOp1, loOp2);
5964
5965         // The low set must be unsigned
5966         emitJumpKind jumpKindLo = genJumpKindForOper(tree->gtOper, CK_UNSIGNED);
5967
5968         inst_SET(jumpKindLo, targetReg);
5969         inst_JMP(EJ_jmp, labelFinal);
5970
5971         // Define the label for hi jump target here. If we have jumped here, we want to set
5972         // the target register based on the jump kind of the actual compare type.
5973
5974         genDefineTempLabel(labelHi);
5975         inst_SET(genJumpKindForOper(tree->gtOper, compareKind), targetReg);
5976
5977         genDefineTempLabel(labelFinal);
5978         // Set the higher bytes to 0
5979         inst_RV_RV(ins_Move_Extend(TYP_UBYTE, true), targetReg, targetReg, TYP_UBYTE, emitTypeSize(TYP_UBYTE));
5980         genProduceReg(tree);
5981     }
5982     else
5983     {
5984         // If the compare is unsigned, or if the sign doesn't change the set instruction, we can use
5985         // the same set logic for both the hi and lo compare, so we don't need to jump to a high label,
5986         // we can just jump to the set that the lo compare will use.
5987
5988         // We only have to check for equality for the hi comparison. If they are not equal, then the set will
5989         // do the right thing. If they are equal, we have to check the lo halves.
5990         inst_JMP(EJ_jne, labelFinal);
5991
5992         // Emit the comparison
5993         getEmitter()->emitInsBinary(ins, cmpAttr, loOp1, loOp2);
5994
5995         // Define the label for hi jump target here. If we have jumped here, we want to set
5996         // the target register based on the jump kind of the lower half (the actual compare
5997         // type). If we have fallen through, then we are doing a normal int compare for the
5998         // lower parts
5999
6000         genDefineTempLabel(labelFinal);
6001
6002         // The low set must be unsigned
6003         emitJumpKind jumpKindLo = genJumpKindForOper(tree->gtOper, CK_UNSIGNED);
6004
6005         inst_SET(jumpKindLo, targetReg);
6006         // Set the higher bytes to 0
6007         inst_RV_RV(ins_Move_Extend(TYP_UBYTE, true), targetReg, targetReg, TYP_UBYTE, emitTypeSize(TYP_UBYTE));
6008         genProduceReg(tree);
6009     }
6010 }
6011 #endif //! defined(_TARGET_64BIT_)
6012
6013 //------------------------------------------------------------------------
6014 // genCompareFloat: Generate code for comparing two floating point values
6015 //
6016 // Arguments:
6017 //    treeNode - the compare tree
6018 //
6019 // Return Value:
6020 //    None.
6021 // Comments:
6022 // SSE2 instruction ucomis[s|d] is performs unordered comparison and
6023 // updates rFLAGS register as follows.
6024 //        Result of compare         ZF  PF CF
6025 //        -----------------        ------------
6026 //        Unordered                 1   1   1     <-- this result implies one of operands of compare is a NAN.
6027 //        Greater                   0   0   0
6028 //        Less Than                 0   0   1
6029 //        Equal                     1   0   0
6030 //
6031 // From the above table the following equalities follow. As per ECMA spec *.UN opcodes perform
6032 // unordered comparison of floating point values.  That is *.UN comparisons result in true when
6033 // one of the operands is a NaN whereas ordered comparisons results in false.
6034 //
6035 //    Opcode          Amd64 equivalent         Comment
6036 //    ------          -----------------        --------
6037 //    BLT.UN(a,b)      ucomis[s|d] a, b        Jb branches if CF=1, which means either a<b or unordered from the above
6038 //                     jb                      table
6039 //
6040 //    BLT(a,b)         ucomis[s|d] b, a        Ja branches if CF=0 and ZF=0, which means b>a that in turn implies a<b
6041 //                     ja
6042 //
6043 //    BGT.UN(a,b)      ucomis[s|d] b, a        branch if b<a or unordered ==> branch if a>b or unordered
6044 //                     jb
6045 //
6046 //    BGT(a, b)        ucomis[s|d] a, b        branch if a>b
6047 //                     ja
6048 //
6049 //    BLE.UN(a,b)      ucomis[s|d] a, b        jbe branches if CF=1 or ZF=1, which implies a<=b or unordered
6050 //                     jbe
6051 //
6052 //    BLE(a,b)         ucomis[s|d] b, a        jae branches if CF=0, which mean b>=a or a<=b
6053 //                     jae
6054 //
6055 //    BGE.UN(a,b)      ucomis[s|d] b, a        branch if b<=a or unordered ==> branch if a>=b or unordered
6056 //                     jbe
6057 //
6058 //    BGE(a,b)         ucomis[s|d] a, b        branch if a>=b
6059 //                     jae
6060 //
6061 //    BEQ.UN(a,b)      ucomis[s|d] a, b        branch if a==b or unordered.  There is no BEQ.UN opcode in ECMA spec.
6062 //                     je                      This case is given for completeness, in case if JIT generates such
6063 //                                             a gentree internally.
6064 //
6065 //    BEQ(a,b)         ucomis[s|d] a, b        From the above table, PF=0 and ZF=1 corresponds to a==b.
6066 //                     jpe L1
6067 //                     je <true label>
6068 //                 L1:
6069 //
6070 //    BNE(a,b)         ucomis[s|d] a, b        branch if a!=b.  There is no BNE opcode in ECMA spec. This case is
6071 //                     jne                     given for completeness, in case if JIT generates such a gentree
6072 //                                             internally.
6073 //
6074 //    BNE.UN(a,b)      ucomis[s|d] a, b        From the above table, PF=1 or ZF=0 implies unordered or a!=b
6075 //                     jpe <true label>
6076 //                     jne <true label>
6077 //
6078 // As we can see from the above equalities that the operands of a compare operator need to be
6079 // reveresed in case of BLT/CLT, BGT.UN/CGT.UN, BLE/CLE, BGE.UN/CGE.UN.
6080 void CodeGen::genCompareFloat(GenTreePtr treeNode)
6081 {
6082     assert(treeNode->OperIsCompare());
6083
6084     GenTreeOp* tree    = treeNode->AsOp();
6085     GenTreePtr op1     = tree->gtOp1;
6086     GenTreePtr op2     = tree->gtOp2;
6087     var_types  op1Type = op1->TypeGet();
6088     var_types  op2Type = op2->TypeGet();
6089
6090     genConsumeOperands(tree);
6091
6092     assert(varTypeIsFloating(op1Type));
6093     assert(op1Type == op2Type);
6094
6095     regNumber   targetReg = treeNode->gtRegNum;
6096     instruction ins;
6097     emitAttr    cmpAttr;
6098
6099     bool reverseOps;
6100     if ((tree->gtFlags & GTF_RELOP_NAN_UN) != 0)
6101     {
6102         // Unordered comparison case
6103         reverseOps = (tree->gtOper == GT_GT || tree->gtOper == GT_GE);
6104     }
6105     else
6106     {
6107         reverseOps = (tree->gtOper == GT_LT || tree->gtOper == GT_LE);
6108     }
6109
6110     if (reverseOps)
6111     {
6112         GenTreePtr tmp = op1;
6113         op1            = op2;
6114         op2            = tmp;
6115     }
6116
6117     ins     = ins_FloatCompare(op1Type);
6118     cmpAttr = emitTypeSize(op1Type);
6119
6120     getEmitter()->emitInsBinary(ins, cmpAttr, op1, op2);
6121
6122     // Are we evaluating this into a register?
6123     if (targetReg != REG_NA)
6124     {
6125         genSetRegToCond(targetReg, tree);
6126         genProduceReg(tree);
6127     }
6128 }
6129
6130 //------------------------------------------------------------------------
6131 // genCompareInt: Generate code for comparing ints or, on amd64, longs.
6132 //
6133 // Arguments:
6134 //    treeNode - the compare tree
6135 //
6136 // Return Value:
6137 //    None.
6138 void CodeGen::genCompareInt(GenTreePtr treeNode)
6139 {
6140     assert(treeNode->OperIsCompare());
6141
6142     GenTreeOp* tree      = treeNode->AsOp();
6143     GenTreePtr op1       = tree->gtOp1;
6144     GenTreePtr op2       = tree->gtOp2;
6145     var_types  op1Type   = op1->TypeGet();
6146     var_types  op2Type   = op2->TypeGet();
6147     regNumber  targetReg = tree->gtRegNum;
6148
6149     // Case of op1 == 0 or op1 != 0:
6150     // Optimize generation of 'test' instruction if op1 sets flags.
6151     //
6152     // Note that if LSRA has inserted any GT_RELOAD/GT_COPY before
6153     // op1, it will not modify the flags set by codegen of op1.
6154     // Similarly op1 could also be reg-optional at its use and
6155     // it was spilled after producing its result in a register.
6156     // Spill code too will not modify the flags set by op1.
6157     GenTree* realOp1 = op1->gtSkipReloadOrCopy();
6158     if (realOp1->gtSetFlags())
6159     {
6160         // op1 must set ZF and SF flags
6161         assert(realOp1->gtSetZSFlags());
6162
6163         // Must be (in)equality against zero.
6164         assert(tree->OperIs(GT_EQ, GT_NE));
6165         assert(op2->IsIntegralConst(0));
6166         assert(op2->isContained());
6167
6168         // Just consume the operands
6169         genConsumeOperands(tree);
6170
6171         // No need to generate test instruction since
6172         // op1 sets flags
6173
6174         // Are we evaluating this into a register?
6175         if (targetReg != REG_NA)
6176         {
6177             genSetRegToCond(targetReg, tree);
6178             genProduceReg(tree);
6179         }
6180
6181         return;
6182     }
6183
6184 #ifdef FEATURE_SIMD
6185     // If we have GT_JTRUE(GT_EQ/NE(GT_SIMD((in)Equality, v1, v2), true/false)),
6186     // then we don't need to generate code for GT_EQ/GT_NE, since SIMD (in)Equality intrinsic
6187     // would set or clear Zero flag.
6188     if ((targetReg == REG_NA) && tree->OperIs(GT_EQ, GT_NE))
6189     {
6190         // Is it a SIMD (in)Equality that doesn't need to materialize result into a register?
6191         if ((op1->gtRegNum == REG_NA) && op1->IsSIMDEqualityOrInequality())
6192         {
6193             // Must be comparing against true or false.
6194             assert(op2->IsIntegralConst(0) || op2->IsIntegralConst(1));
6195             assert(op2->isContainedIntOrIImmed());
6196
6197             // In this case SIMD (in)Equality will set or clear
6198             // Zero flag, based on which GT_JTRUE would generate
6199             // the right conditional jump.
6200             return;
6201         }
6202     }
6203 #endif // FEATURE_SIMD
6204
6205     genConsumeOperands(tree);
6206
6207     // TODO-CQ: We should be able to support swapping op1 and op2 to generate cmp reg, imm.
6208     // https://github.com/dotnet/coreclr/issues/7270
6209     assert(!op1->isContainedIntOrIImmed()); // We no longer support
6210     assert(!varTypeIsFloating(op2Type));
6211
6212     instruction ins;
6213
6214     if (tree->OperIs(GT_TEST_EQ, GT_TEST_NE))
6215     {
6216         ins = INS_test;
6217     }
6218     else if (op1->isUsedFromReg() && op2->IsIntegralConst(0))
6219     {
6220         // We're comparing a register to 0 so we can generate "test reg1, reg1"
6221         // instead of the longer "cmp reg1, 0"
6222         ins = INS_test;
6223         op2 = op1;
6224     }
6225     else
6226     {
6227         ins = INS_cmp;
6228     }
6229
6230     var_types type;
6231
6232     if (op1Type == op2Type)
6233     {
6234         type = op1Type;
6235     }
6236     else if (genTypeSize(op1Type) == genTypeSize(op2Type))
6237     {
6238         // If the types are different but have the same size then we'll use TYP_INT or TYP_LONG.
6239         // This primarily deals with small type mixes (e.g. byte/ubyte) that need to be widened
6240         // and compared as int. We should not get long type mixes here but handle that as well
6241         // just in case.
6242         type = genTypeSize(op1Type) == 8 ? TYP_LONG : TYP_INT;
6243     }
6244     else
6245     {
6246         // In the types are different simply use TYP_INT. This deals with small type/int type
6247         // mixes (e.g. byte/short ubyte/int) that need to be widened and compared as int.
6248         // Lowering is expected to handle any mixes that involve long types (e.g. int/long).
6249         type = TYP_INT;
6250     }
6251
6252     // The common type cannot be larger than the machine word size
6253     assert(genTypeSize(type) <= genTypeSize(TYP_I_IMPL));
6254     // The common type cannot be smaller than any of the operand types, we're probably mixing int/long
6255     assert(genTypeSize(type) >= max(genTypeSize(op1Type), genTypeSize(op2Type)));
6256     // TYP_UINT and TYP_ULONG should not appear here, only small types can be unsigned
6257     assert(!varTypeIsUnsigned(type) || varTypeIsSmall(type));
6258     // Small unsigned int types (TYP_BOOL can use anything) should use unsigned comparisons
6259     assert(!(varTypeIsSmallInt(type) && varTypeIsUnsigned(type)) || ((tree->gtFlags & GTF_UNSIGNED) != 0));
6260     // If op1 is smaller then it cannot be in memory, we're probably missing a cast
6261     assert((genTypeSize(op1Type) >= genTypeSize(type)) || !op1->isUsedFromMemory());
6262     // If op2 is smaller then it cannot be in memory, we're probably missing a cast
6263     assert((genTypeSize(op2Type) >= genTypeSize(type)) || !op2->isUsedFromMemory());
6264     // If op2 is a constant then it should fit in the common type
6265     assert(!op2->IsCnsIntOrI() || genTypeCanRepresentValue(type, op2->AsIntCon()->IconValue()));
6266
6267     getEmitter()->emitInsBinary(ins, emitTypeSize(type), op1, op2);
6268
6269     // Are we evaluating this into a register?
6270     if (targetReg != REG_NA)
6271     {
6272         genSetRegToCond(targetReg, tree);
6273         genProduceReg(tree);
6274     }
6275 }
6276
6277 //-------------------------------------------------------------------------------------------
6278 // genSetRegToCond:  Set a register 'dstReg' to the appropriate one or zero value
6279 //                   corresponding to a binary Relational operator result.
6280 //
6281 // Arguments:
6282 //   dstReg          - The target register to set to 1 or 0
6283 //   tree            - The GenTree Relop node that was used to set the Condition codes
6284 //
6285 // Return Value:     none
6286 //
6287 // Notes:
6288 //    A full 64-bit value of either 1 or 0 is setup in the 'dstReg'
6289 //-------------------------------------------------------------------------------------------
6290
6291 void CodeGen::genSetRegToCond(regNumber dstReg, GenTreePtr tree)
6292 {
6293     noway_assert((genRegMask(dstReg) & RBM_BYTE_REGS) != 0);
6294
6295     emitJumpKind jumpKind[2];
6296     bool         branchToTrueLabel[2];
6297     genJumpKindsForTree(tree, jumpKind, branchToTrueLabel);
6298
6299     if (jumpKind[1] == EJ_NONE)
6300     {
6301         // Set (lower byte of) reg according to the flags
6302         inst_SET(jumpKind[0], dstReg);
6303     }
6304     else
6305     {
6306 #ifdef DEBUG
6307         // jmpKind[1] != EJ_NONE implies BEQ and BEN.UN of floating point values.
6308         // These are represented by two conditions.
6309         if (tree->gtOper == GT_EQ)
6310         {
6311             // This must be an ordered comparison.
6312             assert((tree->gtFlags & GTF_RELOP_NAN_UN) == 0);
6313         }
6314         else
6315         {
6316             // This must be BNE.UN
6317             assert((tree->gtOper == GT_NE) && ((tree->gtFlags & GTF_RELOP_NAN_UN) != 0));
6318         }
6319 #endif
6320
6321         // Here is the sample code generated in each case:
6322         // BEQ ==  cmp, jpe <false label>, je <true label>
6323         // That is, to materialize comparison reg needs to be set if PF=0 and ZF=1
6324         //      setnp reg  // if (PF==0) reg = 1 else reg = 0
6325         //      jpe L1     // Jmp if PF==1
6326         //      sete reg
6327         //  L1:
6328         //
6329         // BNE.UN == cmp, jpe <true label>, jne <true label>
6330         // That is, to materialize the comparison reg needs to be set if either PF=1 or ZF=0;
6331         //     setp reg
6332         //     jpe L1
6333         //     setne reg
6334         //  L1:
6335
6336         // reverse the jmpkind condition before setting dstReg if it is to false label.
6337         inst_SET(branchToTrueLabel[0] ? jumpKind[0] : emitter::emitReverseJumpKind(jumpKind[0]), dstReg);
6338
6339         BasicBlock* label = genCreateTempLabel();
6340         inst_JMP(jumpKind[0], label);
6341
6342         // second branch is always to true label
6343         assert(branchToTrueLabel[1]);
6344         inst_SET(jumpKind[1], dstReg);
6345         genDefineTempLabel(label);
6346     }
6347
6348     var_types treeType = tree->TypeGet();
6349     if (treeType == TYP_INT || treeType == TYP_LONG)
6350     {
6351         // Set the higher bytes to 0
6352         inst_RV_RV(ins_Move_Extend(TYP_UBYTE, true), dstReg, dstReg, TYP_UBYTE, emitTypeSize(TYP_UBYTE));
6353     }
6354     else
6355     {
6356         noway_assert(treeType == TYP_BYTE);
6357     }
6358 }
6359
6360 #if !defined(_TARGET_64BIT_)
6361 //------------------------------------------------------------------------
6362 // genLongToIntCast: Generate code for long to int casts on x86.
6363 //
6364 // Arguments:
6365 //    cast - The GT_CAST node
6366 //
6367 // Return Value:
6368 //    None.
6369 //
6370 // Assumptions:
6371 //    The cast node and its sources (via GT_LONG) must have been assigned registers.
6372 //    The destination cannot be a floating point type or a small integer type.
6373 //
6374 void CodeGen::genLongToIntCast(GenTree* cast)
6375 {
6376     assert(cast->OperGet() == GT_CAST);
6377
6378     GenTree* src = cast->gtGetOp1();
6379     noway_assert(src->OperGet() == GT_LONG);
6380
6381     genConsumeRegs(src);
6382
6383     var_types srcType  = ((cast->gtFlags & GTF_UNSIGNED) != 0) ? TYP_ULONG : TYP_LONG;
6384     var_types dstType  = cast->CastToType();
6385     regNumber loSrcReg = src->gtGetOp1()->gtRegNum;
6386     regNumber hiSrcReg = src->gtGetOp2()->gtRegNum;
6387     regNumber dstReg   = cast->gtRegNum;
6388
6389     assert((dstType == TYP_INT) || (dstType == TYP_UINT));
6390     assert(genIsValidIntReg(loSrcReg));
6391     assert(genIsValidIntReg(hiSrcReg));
6392     assert(genIsValidIntReg(dstReg));
6393
6394     if (cast->gtOverflow())
6395     {
6396         //
6397         // Generate an overflow check for [u]long to [u]int casts:
6398         //
6399         // long  -> int  - check if the upper 33 bits are all 0 or all 1
6400         //
6401         // ulong -> int  - check if the upper 33 bits are all 0
6402         //
6403         // long  -> uint - check if the upper 32 bits are all 0
6404         // ulong -> uint - check if the upper 32 bits are all 0
6405         //
6406
6407         if ((srcType == TYP_LONG) && (dstType == TYP_INT))
6408         {
6409             BasicBlock* allOne  = genCreateTempLabel();
6410             BasicBlock* success = genCreateTempLabel();
6411
6412             inst_RV_RV(INS_test, loSrcReg, loSrcReg, TYP_INT, EA_4BYTE);
6413             inst_JMP(EJ_js, allOne);
6414
6415             inst_RV_RV(INS_test, hiSrcReg, hiSrcReg, TYP_INT, EA_4BYTE);
6416             genJumpToThrowHlpBlk(EJ_jne, SCK_OVERFLOW);
6417             inst_JMP(EJ_jmp, success);
6418
6419             genDefineTempLabel(allOne);
6420             inst_RV_IV(INS_cmp, hiSrcReg, -1, EA_4BYTE);
6421             genJumpToThrowHlpBlk(EJ_jne, SCK_OVERFLOW);
6422
6423             genDefineTempLabel(success);
6424         }
6425         else
6426         {
6427             if ((srcType == TYP_ULONG) && (dstType == TYP_INT))
6428             {
6429                 inst_RV_RV(INS_test, loSrcReg, loSrcReg, TYP_INT, EA_4BYTE);
6430                 genJumpToThrowHlpBlk(EJ_js, SCK_OVERFLOW);
6431             }
6432
6433             inst_RV_RV(INS_test, hiSrcReg, hiSrcReg, TYP_INT, EA_4BYTE);
6434             genJumpToThrowHlpBlk(EJ_jne, SCK_OVERFLOW);
6435         }
6436     }
6437
6438     if (dstReg != loSrcReg)
6439     {
6440         inst_RV_RV(INS_mov, dstReg, loSrcReg, TYP_INT, EA_4BYTE);
6441     }
6442
6443     genProduceReg(cast);
6444 }
6445 #endif
6446
6447 //------------------------------------------------------------------------
6448 // genIntToIntCast: Generate code for an integer cast
6449 //    This method handles integer overflow checking casts
6450 //    as well as ordinary integer casts.
6451 //
6452 // Arguments:
6453 //    treeNode - The GT_CAST node
6454 //
6455 // Return Value:
6456 //    None.
6457 //
6458 // Assumptions:
6459 //    The treeNode is not a contained node and must have an assigned register.
6460 //    For a signed convert from byte, the source must be in a byte-addressable register.
6461 //    Neither the source nor target type can be a floating point type.
6462 //
6463 // TODO-XArch-CQ: Allow castOp to be a contained node without an assigned register.
6464 // TODO: refactor to use getCastDescription
6465 //
6466 void CodeGen::genIntToIntCast(GenTreePtr treeNode)
6467 {
6468     assert(treeNode->OperGet() == GT_CAST);
6469
6470     GenTreePtr castOp  = treeNode->gtCast.CastOp();
6471     var_types  srcType = genActualType(castOp->TypeGet());
6472     noway_assert(genTypeSize(srcType) >= 4);
6473
6474 #ifdef _TARGET_X86_
6475     if (varTypeIsLong(srcType))
6476     {
6477         genLongToIntCast(treeNode);
6478         return;
6479     }
6480 #endif // _TARGET_X86_
6481
6482     regNumber targetReg     = treeNode->gtRegNum;
6483     regNumber sourceReg     = castOp->gtRegNum;
6484     var_types dstType       = treeNode->CastToType();
6485     bool      isUnsignedDst = varTypeIsUnsigned(dstType);
6486     bool      isUnsignedSrc = varTypeIsUnsigned(srcType);
6487
6488     // if necessary, force the srcType to unsigned when the GT_UNSIGNED flag is set
6489     if (!isUnsignedSrc && (treeNode->gtFlags & GTF_UNSIGNED) != 0)
6490     {
6491         srcType       = genUnsignedType(srcType);
6492         isUnsignedSrc = true;
6493     }
6494
6495     bool requiresOverflowCheck = false;
6496
6497     assert(genIsValidIntReg(targetReg));
6498     assert(genIsValidIntReg(sourceReg));
6499
6500     instruction ins     = INS_invalid;
6501     emitAttr    srcSize = EA_ATTR(genTypeSize(srcType));
6502     emitAttr    dstSize = EA_ATTR(genTypeSize(dstType));
6503
6504     if (srcSize < dstSize)
6505     {
6506         // Widening cast
6507         // Is this an Overflow checking cast?
6508         // We only need to handle one case, as the other casts can never overflow.
6509         //   cast from TYP_INT to TYP_ULONG
6510         //
6511         if (treeNode->gtOverflow() && (srcType == TYP_INT) && (dstType == TYP_ULONG))
6512         {
6513             requiresOverflowCheck = true;
6514             ins                   = INS_mov;
6515         }
6516         else
6517         {
6518             noway_assert(srcSize < EA_PTRSIZE);
6519
6520             ins = ins_Move_Extend(srcType, castOp->InReg());
6521
6522             /*
6523                 Special case: ins_Move_Extend assumes the destination type is no bigger
6524                 than TYP_INT.  movsx and movzx can already extend all the way to
6525                 64-bit, and a regular 32-bit mov clears the high 32 bits (like the non-existant movzxd),
6526                 but for a sign extension from TYP_INT to TYP_LONG, we need to use movsxd opcode.
6527             */
6528             if (!isUnsignedSrc && !isUnsignedDst)
6529             {
6530 #ifdef _TARGET_X86_
6531                 NYI_X86("Cast to 64 bit for x86/RyuJIT");
6532 #else  // !_TARGET_X86_
6533                 ins = INS_movsxd;
6534 #endif // !_TARGET_X86_
6535             }
6536         }
6537     }
6538     else
6539     {
6540         // Narrowing cast, or sign-changing cast
6541         noway_assert(srcSize >= dstSize);
6542
6543         // Is this an Overflow checking cast?
6544         if (treeNode->gtOverflow())
6545         {
6546             requiresOverflowCheck = true;
6547             ins                   = INS_mov;
6548         }
6549         else
6550         {
6551             ins = ins_Move_Extend(dstType, castOp->InReg());
6552         }
6553     }
6554
6555     noway_assert(ins != INS_invalid);
6556
6557     genConsumeReg(castOp);
6558
6559     if (requiresOverflowCheck)
6560     {
6561         ssize_t typeMin        = 0;
6562         ssize_t typeMax        = 0;
6563         ssize_t typeMask       = 0;
6564         bool    needScratchReg = false;
6565         bool    signCheckOnly  = false;
6566
6567         /* Do we need to compare the value, or just check masks */
6568
6569         switch (dstType)
6570         {
6571             case TYP_BYTE:
6572                 typeMask = ssize_t((int)0xFFFFFF80);
6573                 typeMin  = SCHAR_MIN;
6574                 typeMax  = SCHAR_MAX;
6575                 break;
6576
6577             case TYP_UBYTE:
6578                 typeMask = ssize_t((int)0xFFFFFF00L);
6579                 break;
6580
6581             case TYP_SHORT:
6582                 typeMask = ssize_t((int)0xFFFF8000);
6583                 typeMin  = SHRT_MIN;
6584                 typeMax  = SHRT_MAX;
6585                 break;
6586
6587             case TYP_CHAR:
6588                 typeMask = ssize_t((int)0xFFFF0000L);
6589                 break;
6590
6591             case TYP_INT:
6592                 if (srcType == TYP_UINT)
6593                 {
6594                     signCheckOnly = true;
6595                 }
6596                 else
6597                 {
6598                     typeMask = 0xFFFFFFFF80000000LL;
6599                     typeMin  = INT_MIN;
6600                     typeMax  = INT_MAX;
6601                 }
6602                 break;
6603
6604             case TYP_UINT:
6605                 if (srcType == TYP_INT)
6606                 {
6607                     signCheckOnly = true;
6608                 }
6609                 else
6610                 {
6611                     needScratchReg = true;
6612                 }
6613                 break;
6614
6615             case TYP_LONG:
6616                 noway_assert(srcType == TYP_ULONG);
6617                 signCheckOnly = true;
6618                 break;
6619
6620             case TYP_ULONG:
6621                 noway_assert((srcType == TYP_LONG) || (srcType == TYP_INT));
6622                 signCheckOnly = true;
6623                 break;
6624
6625             default:
6626                 NO_WAY("Unknown type");
6627                 return;
6628         }
6629
6630         if (signCheckOnly)
6631         {
6632             // We only need to check for a negative value in sourceReg
6633             inst_RV_IV(INS_cmp, sourceReg, 0, srcSize);
6634             genJumpToThrowHlpBlk(EJ_jl, SCK_OVERFLOW);
6635         }
6636         else
6637         {
6638             // When we are converting from unsigned or to unsigned, we
6639             // will only have to check for any bits set using 'typeMask'
6640             if (isUnsignedSrc || isUnsignedDst)
6641             {
6642                 if (needScratchReg)
6643                 {
6644                     regNumber tmpReg = treeNode->GetSingleTempReg();
6645                     inst_RV_RV(INS_mov, tmpReg, sourceReg, TYP_LONG); // Move the 64-bit value to a writeable temp reg
6646                     inst_RV_SH(INS_SHIFT_RIGHT_LOGICAL, srcSize, tmpReg, 32); // Shift right by 32 bits
6647                     genJumpToThrowHlpBlk(EJ_jne, SCK_OVERFLOW);               // Throw if result shift is non-zero
6648                 }
6649                 else
6650                 {
6651                     noway_assert(typeMask != 0);
6652                     inst_RV_IV(INS_TEST, sourceReg, typeMask, srcSize);
6653                     genJumpToThrowHlpBlk(EJ_jne, SCK_OVERFLOW);
6654                 }
6655             }
6656             else
6657             {
6658                 // For a narrowing signed cast
6659                 //
6660                 // We must check the value is in a signed range.
6661
6662                 // Compare with the MAX
6663
6664                 noway_assert((typeMin != 0) && (typeMax != 0));
6665
6666                 inst_RV_IV(INS_cmp, sourceReg, typeMax, srcSize);
6667                 genJumpToThrowHlpBlk(EJ_jg, SCK_OVERFLOW);
6668
6669                 // Compare with the MIN
6670
6671                 inst_RV_IV(INS_cmp, sourceReg, typeMin, srcSize);
6672                 genJumpToThrowHlpBlk(EJ_jl, SCK_OVERFLOW);
6673             }
6674         }
6675
6676         if (targetReg != sourceReg
6677 #ifdef _TARGET_AMD64_
6678             // On amd64, we can hit this path for a same-register
6679             // 4-byte to 8-byte widening conversion, and need to
6680             // emit the instruction to set the high bits correctly.
6681             || (dstSize == EA_8BYTE && srcSize == EA_4BYTE)
6682 #endif // _TARGET_AMD64_
6683                 )
6684             inst_RV_RV(ins, targetReg, sourceReg, srcType, srcSize);
6685     }
6686     else // non-overflow checking cast
6687     {
6688         // We may have code transformations that result in casts where srcType is the same as dstType.
6689         // e.g. Bug 824281, in which a comma is split by the rationalizer, leaving an assignment of a
6690         // long constant to a long lclVar.
6691         if (srcType == dstType)
6692         {
6693             ins = INS_mov;
6694         }
6695         /* Is the value sitting in a non-byte-addressable register? */
6696         else if (castOp->InReg() && (dstSize == EA_1BYTE) && !isByteReg(sourceReg))
6697         {
6698             if (isUnsignedDst)
6699             {
6700                 // for unsigned values we can AND, so it need not be a byte register
6701                 ins = INS_AND;
6702             }
6703             else
6704             {
6705                 // Move the value into a byte register
6706                 noway_assert(!"Signed byte convert from non-byte-addressable register");
6707             }
6708
6709             /* Generate "mov targetReg, castOp->gtReg */
6710             if (targetReg != sourceReg)
6711             {
6712                 inst_RV_RV(INS_mov, targetReg, sourceReg, srcType, srcSize);
6713             }
6714         }
6715
6716         if (ins == INS_AND)
6717         {
6718             noway_assert(isUnsignedDst);
6719
6720             /* Generate "and reg, MASK */
6721             unsigned fillPattern;
6722             if (dstSize == EA_1BYTE)
6723             {
6724                 fillPattern = 0xff;
6725             }
6726             else if (dstSize == EA_2BYTE)
6727             {
6728                 fillPattern = 0xffff;
6729             }
6730             else
6731             {
6732                 fillPattern = 0xffffffff;
6733             }
6734
6735             inst_RV_IV(INS_AND, targetReg, fillPattern, EA_4BYTE);
6736         }
6737 #ifdef _TARGET_AMD64_
6738         else if (ins == INS_movsxd)
6739         {
6740             inst_RV_RV(ins, targetReg, sourceReg, srcType, srcSize);
6741         }
6742 #endif // _TARGET_AMD64_
6743         else if (ins == INS_mov)
6744         {
6745             if (targetReg != sourceReg
6746 #ifdef _TARGET_AMD64_
6747                 // On amd64, 'mov' is the opcode used to zero-extend from
6748                 // 4 bytes to 8 bytes.
6749                 || (dstSize == EA_8BYTE && srcSize == EA_4BYTE)
6750 #endif // _TARGET_AMD64_
6751                     )
6752             {
6753                 inst_RV_RV(ins, targetReg, sourceReg, srcType, srcSize);
6754             }
6755         }
6756         else
6757         {
6758             noway_assert(ins == INS_movsx || ins == INS_movzx);
6759             noway_assert(srcSize >= dstSize);
6760
6761             /* Generate "mov targetReg, castOp->gtReg */
6762             inst_RV_RV(ins, targetReg, sourceReg, srcType, dstSize);
6763         }
6764     }
6765
6766     genProduceReg(treeNode);
6767 }
6768
6769 //------------------------------------------------------------------------
6770 // genFloatToFloatCast: Generate code for a cast between float and double
6771 //
6772 // Arguments:
6773 //    treeNode - The GT_CAST node
6774 //
6775 // Return Value:
6776 //    None.
6777 //
6778 // Assumptions:
6779 //    Cast is a non-overflow conversion.
6780 //    The treeNode must have an assigned register.
6781 //    The cast is between float and double or vice versa.
6782 //
6783 void CodeGen::genFloatToFloatCast(GenTreePtr treeNode)
6784 {
6785     // float <--> double conversions are always non-overflow ones
6786     assert(treeNode->OperGet() == GT_CAST);
6787     assert(!treeNode->gtOverflow());
6788
6789     regNumber targetReg = treeNode->gtRegNum;
6790     assert(genIsValidFloatReg(targetReg));
6791
6792     GenTreePtr op1 = treeNode->gtOp.gtOp1;
6793 #ifdef DEBUG
6794     // If not contained, must be a valid float reg.
6795     if (op1->isUsedFromReg())
6796     {
6797         assert(genIsValidFloatReg(op1->gtRegNum));
6798     }
6799 #endif
6800
6801     var_types dstType = treeNode->CastToType();
6802     var_types srcType = op1->TypeGet();
6803     assert(varTypeIsFloating(srcType) && varTypeIsFloating(dstType));
6804
6805     genConsumeOperands(treeNode->AsOp());
6806     if (srcType == dstType && (op1->isUsedFromReg() && (targetReg == op1->gtRegNum)))
6807     {
6808         // source and destinations types are the same and also reside in the same register.
6809         // we just need to consume and produce the reg in this case.
6810         ;
6811     }
6812     else
6813     {
6814         instruction ins = ins_FloatConv(dstType, srcType);
6815         getEmitter()->emitInsBinary(ins, emitTypeSize(dstType), treeNode, op1);
6816     }
6817
6818     genProduceReg(treeNode);
6819 }
6820
6821 //------------------------------------------------------------------------
6822 // genIntToFloatCast: Generate code to cast an int/long to float/double
6823 //
6824 // Arguments:
6825 //    treeNode - The GT_CAST node
6826 //
6827 // Return Value:
6828 //    None.
6829 //
6830 // Assumptions:
6831 //    Cast is a non-overflow conversion.
6832 //    The treeNode must have an assigned register.
6833 //    SrcType= int32/uint32/int64/uint64 and DstType=float/double.
6834 //
6835 void CodeGen::genIntToFloatCast(GenTreePtr treeNode)
6836 {
6837     // int type --> float/double conversions are always non-overflow ones
6838     assert(treeNode->OperGet() == GT_CAST);
6839     assert(!treeNode->gtOverflow());
6840
6841     regNumber targetReg = treeNode->gtRegNum;
6842     assert(genIsValidFloatReg(targetReg));
6843
6844     GenTreePtr op1 = treeNode->gtOp.gtOp1;
6845 #ifdef DEBUG
6846     if (op1->isUsedFromReg())
6847     {
6848         assert(genIsValidIntReg(op1->gtRegNum));
6849     }
6850 #endif
6851
6852     var_types dstType = treeNode->CastToType();
6853     var_types srcType = op1->TypeGet();
6854     assert(!varTypeIsFloating(srcType) && varTypeIsFloating(dstType));
6855
6856 #if !defined(_TARGET_64BIT_)
6857     // We expect morph to replace long to float/double casts with helper calls
6858     noway_assert(!varTypeIsLong(srcType));
6859 #endif // !defined(_TARGET_64BIT_)
6860
6861     // Since xarch emitter doesn't handle reporting gc-info correctly while casting away gc-ness we
6862     // ensure srcType of a cast is non gc-type.  Codegen should never see BYREF as source type except
6863     // for GT_LCL_VAR_ADDR and GT_LCL_FLD_ADDR that represent stack addresses and can be considered
6864     // as TYP_I_IMPL. In all other cases where src operand is a gc-type and not known to be on stack,
6865     // Front-end (see fgMorphCast()) ensures this by assigning gc-type local to a non gc-type
6866     // temp and using temp as operand of cast operation.
6867     if (srcType == TYP_BYREF)
6868     {
6869         noway_assert(op1->OperGet() == GT_LCL_VAR_ADDR || op1->OperGet() == GT_LCL_FLD_ADDR);
6870         srcType = TYP_I_IMPL;
6871     }
6872
6873     // force the srcType to unsigned if GT_UNSIGNED flag is set
6874     if (treeNode->gtFlags & GTF_UNSIGNED)
6875     {
6876         srcType = genUnsignedType(srcType);
6877     }
6878
6879     noway_assert(!varTypeIsGC(srcType));
6880
6881     // We should never be seeing srcType whose size is not sizeof(int) nor sizeof(long).
6882     // For conversions from byte/sbyte/int16/uint16 to float/double, we would expect
6883     // either the front-end or lowering phase to have generated two levels of cast.
6884     // The first one is for widening smaller int type to int32 and the second one is
6885     // to the float/double.
6886     emitAttr srcSize = EA_ATTR(genTypeSize(srcType));
6887     noway_assert((srcSize == EA_ATTR(genTypeSize(TYP_INT))) || (srcSize == EA_ATTR(genTypeSize(TYP_LONG))));
6888
6889     // Also we don't expect to see uint32 -> float/double and uint64 -> float conversions
6890     // here since they should have been lowered apropriately.
6891     noway_assert(srcType != TYP_UINT);
6892     noway_assert((srcType != TYP_ULONG) || (dstType != TYP_FLOAT));
6893
6894     // To convert int to a float/double, cvtsi2ss/sd SSE2 instruction is used
6895     // which does a partial write to lower 4/8 bytes of xmm register keeping the other
6896     // upper bytes unmodified.  If "cvtsi2ss/sd xmmReg, r32/r64" occurs inside a loop,
6897     // the partial write could introduce a false dependency and could cause a stall
6898     // if there are further uses of xmmReg. We have such a case occuring with a
6899     // customer reported version of SpectralNorm benchmark, resulting in 2x perf
6900     // regression.  To avoid false dependency, we emit "xorps xmmReg, xmmReg" before
6901     // cvtsi2ss/sd instruction.
6902
6903     genConsumeOperands(treeNode->AsOp());
6904     getEmitter()->emitIns_R_R(INS_xorps, EA_4BYTE, treeNode->gtRegNum, treeNode->gtRegNum);
6905
6906     // Note that here we need to specify srcType that will determine
6907     // the size of source reg/mem operand and rex.w prefix.
6908     instruction ins = ins_FloatConv(dstType, TYP_INT);
6909     getEmitter()->emitInsBinary(ins, emitTypeSize(srcType), treeNode, op1);
6910
6911     // Handle the case of srcType = TYP_ULONG. SSE2 conversion instruction
6912     // will interpret ULONG value as LONG.  Hence we need to adjust the
6913     // result if sign-bit of srcType is set.
6914     if (srcType == TYP_ULONG)
6915     {
6916         // The instruction sequence below is less accurate than what clang
6917         // and gcc generate. However, we keep the current sequence for backward compatiblity.
6918         // If we change the instructions below, FloatingPointUtils::convertUInt64ToDobule
6919         // should be also updated for consistent conversion result.
6920         assert(dstType == TYP_DOUBLE);
6921         assert(op1->isUsedFromReg());
6922
6923         // Set the flags without modifying op1.
6924         // test op1Reg, op1Reg
6925         inst_RV_RV(INS_test, op1->gtRegNum, op1->gtRegNum, srcType);
6926
6927         // No need to adjust result if op1 >= 0 i.e. positive
6928         // Jge label
6929         BasicBlock* label = genCreateTempLabel();
6930         inst_JMP(EJ_jge, label);
6931
6932         // Adjust the result
6933         // result = result + 0x43f00000 00000000
6934         // addsd resultReg,  0x43f00000 00000000
6935         GenTreePtr* cns = &u8ToDblBitmask;
6936         if (*cns == nullptr)
6937         {
6938             double d;
6939             static_assert_no_msg(sizeof(double) == sizeof(__int64));
6940             *((__int64*)&d) = 0x43f0000000000000LL;
6941
6942             *cns = genMakeConst(&d, dstType, treeNode, true);
6943         }
6944         inst_RV_TT(INS_addsd, treeNode->gtRegNum, *cns);
6945
6946         genDefineTempLabel(label);
6947     }
6948
6949     genProduceReg(treeNode);
6950 }
6951
6952 //------------------------------------------------------------------------
6953 // genFloatToIntCast: Generate code to cast float/double to int/long
6954 //
6955 // Arguments:
6956 //    treeNode - The GT_CAST node
6957 //
6958 // Return Value:
6959 //    None.
6960 //
6961 // Assumptions:
6962 //    Cast is a non-overflow conversion.
6963 //    The treeNode must have an assigned register.
6964 //    SrcType=float/double and DstType= int32/uint32/int64/uint64
6965 //
6966 // TODO-XArch-CQ: (Low-pri) - generate in-line code when DstType = uint64
6967 //
6968 void CodeGen::genFloatToIntCast(GenTreePtr treeNode)
6969 {
6970     // we don't expect to see overflow detecting float/double --> int type conversions here
6971     // as they should have been converted into helper calls by front-end.
6972     assert(treeNode->OperGet() == GT_CAST);
6973     assert(!treeNode->gtOverflow());
6974
6975     regNumber targetReg = treeNode->gtRegNum;
6976     assert(genIsValidIntReg(targetReg));
6977
6978     GenTreePtr op1 = treeNode->gtOp.gtOp1;
6979 #ifdef DEBUG
6980     if (op1->isUsedFromReg())
6981     {
6982         assert(genIsValidFloatReg(op1->gtRegNum));
6983     }
6984 #endif
6985
6986     var_types dstType = treeNode->CastToType();
6987     var_types srcType = op1->TypeGet();
6988     assert(varTypeIsFloating(srcType) && !varTypeIsFloating(dstType));
6989
6990     // We should never be seeing dstType whose size is neither sizeof(TYP_INT) nor sizeof(TYP_LONG).
6991     // For conversions to byte/sbyte/int16/uint16 from float/double, we would expect the
6992     // front-end or lowering phase to have generated two levels of cast. The first one is
6993     // for float or double to int32/uint32 and the second one for narrowing int32/uint32 to
6994     // the required smaller int type.
6995     emitAttr dstSize = EA_ATTR(genTypeSize(dstType));
6996     noway_assert((dstSize == EA_ATTR(genTypeSize(TYP_INT))) || (dstSize == EA_ATTR(genTypeSize(TYP_LONG))));
6997
6998     // We shouldn't be seeing uint64 here as it should have been converted
6999     // into a helper call by either front-end or lowering phase.
7000     noway_assert(!varTypeIsUnsigned(dstType) || (dstSize != EA_ATTR(genTypeSize(TYP_LONG))));
7001
7002     // If the dstType is TYP_UINT, we have 32-bits to encode the
7003     // float number. Any of 33rd or above bits can be the sign bit.
7004     // To acheive it we pretend as if we are converting it to a long.
7005     if (varTypeIsUnsigned(dstType) && (dstSize == EA_ATTR(genTypeSize(TYP_INT))))
7006     {
7007         dstType = TYP_LONG;
7008     }
7009
7010     // Note that we need to specify dstType here so that it will determine
7011     // the size of destination integer register and also the rex.w prefix.
7012     genConsumeOperands(treeNode->AsOp());
7013     instruction ins = ins_FloatConv(TYP_INT, srcType);
7014     getEmitter()->emitInsBinary(ins, emitTypeSize(dstType), treeNode, op1);
7015     genProduceReg(treeNode);
7016 }
7017
7018 //------------------------------------------------------------------------
7019 // genCkfinite: Generate code for ckfinite opcode.
7020 //
7021 // Arguments:
7022 //    treeNode - The GT_CKFINITE node
7023 //
7024 // Return Value:
7025 //    None.
7026 //
7027 // Assumptions:
7028 //    GT_CKFINITE node has reserved an internal register.
7029 //
7030 // TODO-XArch-CQ - mark the operand as contained if known to be in
7031 // memory (e.g. field or an array element).
7032 //
7033 void CodeGen::genCkfinite(GenTreePtr treeNode)
7034 {
7035     assert(treeNode->OperGet() == GT_CKFINITE);
7036
7037     GenTreePtr op1        = treeNode->gtOp.gtOp1;
7038     var_types  targetType = treeNode->TypeGet();
7039     int        expMask    = (targetType == TYP_FLOAT) ? 0x7F800000 : 0x7FF00000; // Bit mask to extract exponent.
7040     regNumber  targetReg  = treeNode->gtRegNum;
7041
7042     // Extract exponent into a register.
7043     regNumber tmpReg = treeNode->GetSingleTempReg();
7044
7045     genConsumeReg(op1);
7046
7047 #ifdef _TARGET_64BIT_
7048
7049     // Copy the floating-point value to an integer register. If we copied a float to a long, then
7050     // right-shift the value so the high 32 bits of the floating-point value sit in the low 32
7051     // bits of the integer register.
7052     instruction ins = ins_CopyFloatToInt(targetType, (targetType == TYP_FLOAT) ? TYP_INT : TYP_LONG);
7053     inst_RV_RV(ins, op1->gtRegNum, tmpReg, targetType);
7054     if (targetType == TYP_DOUBLE)
7055     {
7056         // right shift by 32 bits to get to exponent.
7057         inst_RV_SH(INS_shr, EA_8BYTE, tmpReg, 32);
7058     }
7059
7060     // Mask exponent with all 1's and check if the exponent is all 1's
7061     inst_RV_IV(INS_and, tmpReg, expMask, EA_4BYTE);
7062     inst_RV_IV(INS_cmp, tmpReg, expMask, EA_4BYTE);
7063
7064     // If exponent is all 1's, throw ArithmeticException
7065     genJumpToThrowHlpBlk(EJ_je, SCK_ARITH_EXCPN);
7066
7067     // if it is a finite value copy it to targetReg
7068     if (targetReg != op1->gtRegNum)
7069     {
7070         inst_RV_RV(ins_Copy(targetType), targetReg, op1->gtRegNum, targetType);
7071     }
7072
7073 #else // !_TARGET_64BIT_
7074
7075     // If the target type is TYP_DOUBLE, we want to extract the high 32 bits into the register.
7076     // There is no easy way to do this. To not require an extra register, we'll use shuffles
7077     // to move the high 32 bits into the low 32 bits, then then shuffle it back, since we
7078     // need to produce the value into the target register.
7079     //
7080     // For TYP_DOUBLE, we'll generate (for targetReg != op1->gtRegNum):
7081     //    movaps targetReg, op1->gtRegNum
7082     //    shufps targetReg, targetReg, 0xB1    // WZYX => ZWXY
7083     //    mov_xmm2i tmpReg, targetReg          // tmpReg <= Y
7084     //    and tmpReg, <mask>
7085     //    cmp tmpReg, <mask>
7086     //    je <throw block>
7087     //    movaps targetReg, op1->gtRegNum   // copy the value again, instead of un-shuffling it
7088     //
7089     // For TYP_DOUBLE with (targetReg == op1->gtRegNum):
7090     //    shufps targetReg, targetReg, 0xB1    // WZYX => ZWXY
7091     //    mov_xmm2i tmpReg, targetReg          // tmpReg <= Y
7092     //    and tmpReg, <mask>
7093     //    cmp tmpReg, <mask>
7094     //    je <throw block>
7095     //    shufps targetReg, targetReg, 0xB1    // ZWXY => WZYX
7096     //
7097     // For TYP_FLOAT, it's the same as _TARGET_64BIT_:
7098     //    mov_xmm2i tmpReg, targetReg          // tmpReg <= low 32 bits
7099     //    and tmpReg, <mask>
7100     //    cmp tmpReg, <mask>
7101     //    je <throw block>
7102     //    movaps targetReg, op1->gtRegNum      // only if targetReg != op1->gtRegNum
7103
7104     regNumber copyToTmpSrcReg; // The register we'll copy to the integer temp.
7105
7106     if (targetType == TYP_DOUBLE)
7107     {
7108         if (targetReg != op1->gtRegNum)
7109         {
7110             inst_RV_RV(ins_Copy(targetType), targetReg, op1->gtRegNum, targetType);
7111         }
7112         inst_RV_RV_IV(INS_shufps, EA_16BYTE, targetReg, targetReg, 0xb1);
7113         copyToTmpSrcReg = targetReg;
7114     }
7115     else
7116     {
7117         copyToTmpSrcReg = op1->gtRegNum;
7118     }
7119
7120     // Copy only the low 32 bits. This will be the high order 32 bits of the floating-point
7121     // value, no matter the floating-point type.
7122     inst_RV_RV(ins_CopyFloatToInt(TYP_FLOAT, TYP_INT), copyToTmpSrcReg, tmpReg, TYP_FLOAT);
7123
7124     // Mask exponent with all 1's and check if the exponent is all 1's
7125     inst_RV_IV(INS_and, tmpReg, expMask, EA_4BYTE);
7126     inst_RV_IV(INS_cmp, tmpReg, expMask, EA_4BYTE);
7127
7128     // If exponent is all 1's, throw ArithmeticException
7129     genJumpToThrowHlpBlk(EJ_je, SCK_ARITH_EXCPN);
7130
7131     if (targetReg != op1->gtRegNum)
7132     {
7133         // In both the TYP_FLOAT and TYP_DOUBLE case, the op1 register is untouched,
7134         // so copy it to the targetReg. This is faster and smaller for TYP_DOUBLE
7135         // than re-shuffling the targetReg.
7136         inst_RV_RV(ins_Copy(targetType), targetReg, op1->gtRegNum, targetType);
7137     }
7138     else if (targetType == TYP_DOUBLE)
7139     {
7140         // We need to re-shuffle the targetReg to get the correct result.
7141         inst_RV_RV_IV(INS_shufps, EA_16BYTE, targetReg, targetReg, 0xb1);
7142     }
7143
7144 #endif // !_TARGET_64BIT_
7145
7146     genProduceReg(treeNode);
7147 }
7148
7149 #ifdef _TARGET_AMD64_
7150 int CodeGenInterface::genSPtoFPdelta()
7151 {
7152     int delta;
7153
7154 #ifdef UNIX_AMD64_ABI
7155
7156     // We require frame chaining on Unix to support native tool unwinding (such as
7157     // unwinding by the native debugger). We have a CLR-only extension to the
7158     // unwind codes (UWOP_SET_FPREG_LARGE) to support SP->FP offsets larger than 240.
7159     // If Unix ever supports EnC, the RSP == RBP assumption will have to be reevaluated.
7160     delta = genTotalFrameSize();
7161
7162 #else // !UNIX_AMD64_ABI
7163
7164     // As per Amd64 ABI, RBP offset from initial RSP can be between 0 and 240 if
7165     // RBP needs to be reported in unwind codes.  This case would arise for methods
7166     // with localloc.
7167     if (compiler->compLocallocUsed)
7168     {
7169         // We cannot base delta computation on compLclFrameSize since it changes from
7170         // tentative to final frame layout and hence there is a possibility of
7171         // under-estimating offset of vars from FP, which in turn results in under-
7172         // estimating instruction size.
7173         //
7174         // To be predictive and so as never to under-estimate offset of vars from FP
7175         // we will always position FP at min(240, outgoing arg area size).
7176         delta = Min(240, (int)compiler->lvaOutgoingArgSpaceSize);
7177     }
7178     else if (compiler->opts.compDbgEnC)
7179     {
7180         // vm assumption on EnC methods is that rsp and rbp are equal
7181         delta = 0;
7182     }
7183     else
7184     {
7185         delta = genTotalFrameSize();
7186     }
7187
7188 #endif // !UNIX_AMD64_ABI
7189
7190     return delta;
7191 }
7192
7193 //---------------------------------------------------------------------
7194 // genTotalFrameSize - return the total size of the stack frame, including local size,
7195 // callee-saved register size, etc. For AMD64, this does not include the caller-pushed
7196 // return address.
7197 //
7198 // Return value:
7199 //    Total frame size
7200 //
7201
7202 int CodeGenInterface::genTotalFrameSize()
7203 {
7204     assert(!IsUninitialized(compiler->compCalleeRegsPushed));
7205
7206     int totalFrameSize = compiler->compCalleeRegsPushed * REGSIZE_BYTES + compiler->compLclFrameSize;
7207
7208     assert(totalFrameSize >= 0);
7209     return totalFrameSize;
7210 }
7211
7212 //---------------------------------------------------------------------
7213 // genCallerSPtoFPdelta - return the offset from Caller-SP to the frame pointer.
7214 // This number is going to be negative, since the Caller-SP is at a higher
7215 // address than the frame pointer.
7216 //
7217 // There must be a frame pointer to call this function!
7218 //
7219 // We can't compute this directly from the Caller-SP, since the frame pointer
7220 // is based on a maximum delta from Initial-SP, so first we find SP, then
7221 // compute the FP offset.
7222
7223 int CodeGenInterface::genCallerSPtoFPdelta()
7224 {
7225     assert(isFramePointerUsed());
7226     int callerSPtoFPdelta;
7227
7228     callerSPtoFPdelta = genCallerSPtoInitialSPdelta() + genSPtoFPdelta();
7229
7230     assert(callerSPtoFPdelta <= 0);
7231     return callerSPtoFPdelta;
7232 }
7233
7234 //---------------------------------------------------------------------
7235 // genCallerSPtoInitialSPdelta - return the offset from Caller-SP to Initial SP.
7236 //
7237 // This number will be negative.
7238
7239 int CodeGenInterface::genCallerSPtoInitialSPdelta()
7240 {
7241     int callerSPtoSPdelta = 0;
7242
7243     callerSPtoSPdelta -= genTotalFrameSize();
7244     callerSPtoSPdelta -= REGSIZE_BYTES; // caller-pushed return address
7245
7246     // compCalleeRegsPushed does not account for the frame pointer
7247     // TODO-Cleanup: shouldn't this be part of genTotalFrameSize?
7248     if (isFramePointerUsed())
7249     {
7250         callerSPtoSPdelta -= REGSIZE_BYTES;
7251     }
7252
7253     assert(callerSPtoSPdelta <= 0);
7254     return callerSPtoSPdelta;
7255 }
7256 #endif // _TARGET_AMD64_
7257
7258 //-----------------------------------------------------------------------------------------
7259 // genSSE2BitwiseOp - generate SSE2 code for the given oper as "Operand BitWiseOp BitMask"
7260 //
7261 // Arguments:
7262 //    treeNode  - tree node
7263 //
7264 // Return value:
7265 //    None
7266 //
7267 // Assumptions:
7268 //     i) tree oper is one of GT_NEG or GT_INTRINSIC Abs()
7269 //    ii) tree type is floating point type.
7270 //   iii) caller of this routine needs to call genProduceReg()
7271 void CodeGen::genSSE2BitwiseOp(GenTreePtr treeNode)
7272 {
7273     regNumber targetReg  = treeNode->gtRegNum;
7274     var_types targetType = treeNode->TypeGet();
7275     assert(varTypeIsFloating(targetType));
7276
7277     float       f;
7278     double      d;
7279     GenTreePtr* bitMask  = nullptr;
7280     instruction ins      = INS_invalid;
7281     void*       cnsAddr  = nullptr;
7282     bool        dblAlign = false;
7283
7284     switch (treeNode->OperGet())
7285     {
7286         case GT_NEG:
7287             // Neg(x) = flip the sign bit.
7288             // Neg(f) = f ^ 0x80000000
7289             // Neg(d) = d ^ 0x8000000000000000
7290             ins = genGetInsForOper(GT_XOR, targetType);
7291             if (targetType == TYP_FLOAT)
7292             {
7293                 bitMask = &negBitmaskFlt;
7294
7295                 static_assert_no_msg(sizeof(float) == sizeof(int));
7296                 *((int*)&f) = 0x80000000;
7297                 cnsAddr     = &f;
7298             }
7299             else
7300             {
7301                 bitMask = &negBitmaskDbl;
7302
7303                 static_assert_no_msg(sizeof(double) == sizeof(__int64));
7304                 *((__int64*)&d) = 0x8000000000000000LL;
7305                 cnsAddr         = &d;
7306                 dblAlign        = true;
7307             }
7308             break;
7309
7310         case GT_INTRINSIC:
7311             assert(treeNode->gtIntrinsic.gtIntrinsicId == CORINFO_INTRINSIC_Abs);
7312
7313             // Abs(x) = set sign-bit to zero
7314             // Abs(f) = f & 0x7fffffff
7315             // Abs(d) = d & 0x7fffffffffffffff
7316             ins = genGetInsForOper(GT_AND, targetType);
7317             if (targetType == TYP_FLOAT)
7318             {
7319                 bitMask = &absBitmaskFlt;
7320
7321                 static_assert_no_msg(sizeof(float) == sizeof(int));
7322                 *((int*)&f) = 0x7fffffff;
7323                 cnsAddr     = &f;
7324             }
7325             else
7326             {
7327                 bitMask = &absBitmaskDbl;
7328
7329                 static_assert_no_msg(sizeof(double) == sizeof(__int64));
7330                 *((__int64*)&d) = 0x7fffffffffffffffLL;
7331                 cnsAddr         = &d;
7332                 dblAlign        = true;
7333             }
7334             break;
7335
7336         default:
7337             assert(!"genSSE2: unsupported oper");
7338             unreached();
7339             break;
7340     }
7341
7342     if (*bitMask == nullptr)
7343     {
7344         assert(cnsAddr != nullptr);
7345         *bitMask = genMakeConst(cnsAddr, targetType, treeNode, dblAlign);
7346     }
7347
7348     // We need an additional register for bitmask.
7349     regNumber tmpReg = treeNode->GetSingleTempReg();
7350
7351     // Move operand into targetReg only if the reg reserved for
7352     // internal purpose is not the same as targetReg.
7353     GenTreePtr op1 = treeNode->gtOp.gtOp1;
7354     assert(op1->isUsedFromReg());
7355     regNumber operandReg = genConsumeReg(op1);
7356     if (tmpReg != targetReg)
7357     {
7358         if (operandReg != targetReg)
7359         {
7360             inst_RV_RV(ins_Copy(targetType), targetReg, operandReg, targetType);
7361         }
7362
7363         operandReg = tmpReg;
7364     }
7365
7366     inst_RV_TT(ins_Load(targetType, false), tmpReg, *bitMask);
7367     assert(ins != INS_invalid);
7368     inst_RV_RV(ins, targetReg, operandReg, targetType);
7369 }
7370
7371 //---------------------------------------------------------------------
7372 // genIntrinsic - generate code for a given intrinsic
7373 //
7374 // Arguments
7375 //    treeNode - the GT_INTRINSIC node
7376 //
7377 // Return value:
7378 //    None
7379 //
7380 void CodeGen::genIntrinsic(GenTreePtr treeNode)
7381 {
7382     // Right now only Sqrt/Abs are treated as math intrinsics.
7383     switch (treeNode->gtIntrinsic.gtIntrinsicId)
7384     {
7385         case CORINFO_INTRINSIC_Sqrt:
7386         {
7387             // Both operand and its result must be of the same floating point type.
7388             GenTreePtr srcNode = treeNode->gtOp.gtOp1;
7389             assert(varTypeIsFloating(srcNode));
7390             assert(srcNode->TypeGet() == treeNode->TypeGet());
7391
7392             genConsumeOperands(treeNode->AsOp());
7393             getEmitter()->emitInsBinary(ins_FloatSqrt(treeNode->TypeGet()), emitTypeSize(treeNode), treeNode, srcNode);
7394             break;
7395         }
7396
7397         case CORINFO_INTRINSIC_Abs:
7398             genSSE2BitwiseOp(treeNode);
7399             break;
7400
7401         default:
7402             assert(!"genIntrinsic: Unsupported intrinsic");
7403             unreached();
7404     }
7405
7406     genProduceReg(treeNode);
7407 }
7408
7409 //-------------------------------------------------------------------------- //
7410 // getBaseVarForPutArgStk - returns the baseVarNum for passing a stack arg.
7411 //
7412 // Arguments
7413 //    treeNode - the GT_PUTARG_STK node
7414 //
7415 // Return value:
7416 //    The number of the base variable.
7417 //
7418 // Note:
7419 //    If tail call the outgoing args are placed in the caller's incoming arg stack space.
7420 //    Otherwise, they go in the outgoing arg area on the current frame.
7421 //
7422 //    On Windows the caller always creates slots (homing space) in its frame for the
7423 //    first 4 arguments of a callee (register passed args). So, the baseVarNum is always 0.
7424 //    For System V systems there is no such calling convention requirement, and the code needs to find
7425 //    the first stack passed argument from the caller. This is done by iterating over
7426 //    all the lvParam variables and finding the first with lvArgReg equals to REG_STK.
7427 //
7428 unsigned CodeGen::getBaseVarForPutArgStk(GenTreePtr treeNode)
7429 {
7430     assert(treeNode->OperGet() == GT_PUTARG_STK);
7431
7432     unsigned baseVarNum;
7433
7434     // Whether to setup stk arg in incoming or out-going arg area?
7435     // Fast tail calls implemented as epilog+jmp = stk arg is setup in incoming arg area.
7436     // All other calls - stk arg is setup in out-going arg area.
7437     if (treeNode->AsPutArgStk()->putInIncomingArgArea())
7438     {
7439         // See the note in the function header re: finding the first stack passed argument.
7440         baseVarNum = getFirstArgWithStackSlot();
7441         assert(baseVarNum != BAD_VAR_NUM);
7442
7443 #ifdef DEBUG
7444         // This must be a fast tail call.
7445         assert(treeNode->AsPutArgStk()->gtCall->AsCall()->IsFastTailCall());
7446
7447         // Since it is a fast tail call, the existence of first incoming arg is guaranteed
7448         // because fast tail call requires that in-coming arg area of caller is >= out-going
7449         // arg area required for tail call.
7450         LclVarDsc* varDsc = &(compiler->lvaTable[baseVarNum]);
7451         assert(varDsc != nullptr);
7452
7453 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
7454         assert(!varDsc->lvIsRegArg && varDsc->lvArgReg == REG_STK);
7455 #else  // !FEATURE_UNIX_AMD64_STRUCT_PASSING
7456         // On Windows this assert is always true. The first argument will always be in REG_ARG_0 or REG_FLTARG_0.
7457         assert(varDsc->lvIsRegArg && (varDsc->lvArgReg == REG_ARG_0 || varDsc->lvArgReg == REG_FLTARG_0));
7458 #endif // !FEATURE_UNIX_AMD64_STRUCT_PASSING
7459 #endif // !DEBUG
7460     }
7461     else
7462     {
7463 #if FEATURE_FIXED_OUT_ARGS
7464         baseVarNum = compiler->lvaOutgoingArgSpaceVar;
7465 #else  // !FEATURE_FIXED_OUT_ARGS
7466         assert(!"No BaseVarForPutArgStk on x86");
7467         baseVarNum = BAD_VAR_NUM;
7468 #endif // !FEATURE_FIXED_OUT_ARGS
7469     }
7470
7471     return baseVarNum;
7472 }
7473
7474 //---------------------------------------------------------------------
7475 // genAlignStackBeforeCall: Align the stack if necessary before a call.
7476 //
7477 // Arguments:
7478 //    putArgStk - the putArgStk node.
7479 //
7480 void CodeGen::genAlignStackBeforeCall(GenTreePutArgStk* putArgStk)
7481 {
7482 #if defined(UNIX_X86_ABI)
7483
7484     genAlignStackBeforeCall(putArgStk->gtCall);
7485
7486 #endif // UNIX_X86_ABI
7487 }
7488
7489 //---------------------------------------------------------------------
7490 // genAlignStackBeforeCall: Align the stack if necessary before a call.
7491 //
7492 // Arguments:
7493 //    call - the call node.
7494 //
7495 void CodeGen::genAlignStackBeforeCall(GenTreeCall* call)
7496 {
7497 #if defined(UNIX_X86_ABI)
7498
7499     // Have we aligned the stack yet?
7500     if (!call->fgArgInfo->IsStkAlignmentDone())
7501     {
7502         // We haven't done any stack alignment yet for this call.  We might need to create
7503         // an alignment adjustment, even if this function itself doesn't have any stack args.
7504         // This can happen if this function call is part of a nested call sequence, and the outer
7505         // call has already pushed some arguments.
7506
7507         unsigned stkLevel = genStackLevel + call->fgArgInfo->GetStkSizeBytes();
7508         call->fgArgInfo->ComputeStackAlignment(stkLevel);
7509
7510         unsigned padStkAlign = call->fgArgInfo->GetStkAlign();
7511         if (padStkAlign != 0)
7512         {
7513             // Now generate the alignment
7514             inst_RV_IV(INS_sub, REG_SPBASE, padStkAlign, EA_PTRSIZE);
7515             AddStackLevel(padStkAlign);
7516             AddNestedAlignment(padStkAlign);
7517         }
7518
7519         call->fgArgInfo->SetStkAlignmentDone();
7520     }
7521
7522 #endif // UNIX_X86_ABI
7523 }
7524
7525 //---------------------------------------------------------------------
7526 // genRemoveAlignmentAfterCall: After a call, remove the alignment
7527 // added before the call, if any.
7528 //
7529 // Arguments:
7530 //    call - the call node.
7531 //    bias - additional stack adjustment
7532 //
7533 // Note:
7534 //    When bias > 0, caller should adjust stack level appropriately as
7535 //    bias is not considered when adjusting stack level.
7536 //
7537 void CodeGen::genRemoveAlignmentAfterCall(GenTreeCall* call, unsigned bias)
7538 {
7539 #if defined(_TARGET_X86_)
7540 #if defined(UNIX_X86_ABI)
7541     // Put back the stack pointer if there was any padding for stack alignment
7542     unsigned padStkAlign  = call->fgArgInfo->GetStkAlign();
7543     unsigned padStkAdjust = padStkAlign + bias;
7544
7545     if (padStkAdjust != 0)
7546     {
7547         inst_RV_IV(INS_add, REG_SPBASE, padStkAdjust, EA_PTRSIZE);
7548         SubtractStackLevel(padStkAlign);
7549         SubtractNestedAlignment(padStkAlign);
7550     }
7551 #else  // UNIX_X86_ABI
7552     if (bias != 0)
7553     {
7554         genAdjustSP(bias);
7555     }
7556 #endif // !UNIX_X86_ABI_
7557 #else  // _TARGET_X86_
7558     assert(bias == 0);
7559 #endif // !_TARGET_X86
7560 }
7561
7562 #ifdef _TARGET_X86_
7563
7564 //---------------------------------------------------------------------
7565 // genAdjustStackForPutArgStk:
7566 //    adjust the stack pointer for a putArgStk node if necessary.
7567 //
7568 // Arguments:
7569 //    putArgStk - the putArgStk node.
7570 //
7571 // Returns: true if the stack pointer was adjusted; false otherwise.
7572 //
7573 // Notes:
7574 //    Sets `m_pushStkArg` to true if the stack arg needs to be pushed,
7575 //    false if the stack arg needs to be stored at the current stack
7576 //    pointer address. This is exactly the opposite of the return value
7577 //    of this function.
7578 //
7579 bool CodeGen::genAdjustStackForPutArgStk(GenTreePutArgStk* putArgStk)
7580 {
7581 #ifdef FEATURE_SIMD
7582     if (varTypeIsSIMD(putArgStk))
7583     {
7584         const unsigned argSize = genTypeSize(putArgStk);
7585         inst_RV_IV(INS_sub, REG_SPBASE, argSize, EA_PTRSIZE);
7586         AddStackLevel(argSize);
7587         m_pushStkArg = false;
7588         return true;
7589     }
7590 #endif // FEATURE_SIMD
7591
7592     const unsigned argSize = putArgStk->getArgSize();
7593
7594     // If the gtPutArgStkKind is one of the push types, we do not pre-adjust the stack.
7595     // This is set in Lowering, and is true if and only if:
7596     // - This argument contains any GC pointers OR
7597     // - It is a GT_FIELD_LIST OR
7598     // - It is less than 16 bytes in size.
7599     CLANG_FORMAT_COMMENT_ANCHOR;
7600
7601 #ifdef DEBUG
7602     switch (putArgStk->gtPutArgStkKind)
7603     {
7604         case GenTreePutArgStk::Kind::RepInstr:
7605         case GenTreePutArgStk::Kind::Unroll:
7606             assert((putArgStk->gtNumberReferenceSlots == 0) && (putArgStk->gtGetOp1()->OperGet() != GT_FIELD_LIST) &&
7607                    (argSize >= 16));
7608             break;
7609         case GenTreePutArgStk::Kind::Push:
7610         case GenTreePutArgStk::Kind::PushAllSlots:
7611             assert((putArgStk->gtNumberReferenceSlots != 0) || (putArgStk->gtGetOp1()->OperGet() == GT_FIELD_LIST) ||
7612                    (argSize < 16));
7613             break;
7614         case GenTreePutArgStk::Kind::Invalid:
7615         default:
7616             assert(!"Uninitialized GenTreePutArgStk::Kind");
7617             break;
7618     }
7619 #endif // DEBUG
7620
7621     if (putArgStk->isPushKind())
7622     {
7623         m_pushStkArg = true;
7624         return false;
7625     }
7626     else
7627     {
7628         m_pushStkArg = false;
7629         inst_RV_IV(INS_sub, REG_SPBASE, argSize, EA_PTRSIZE);
7630         AddStackLevel(argSize);
7631         return true;
7632     }
7633 }
7634
7635 //---------------------------------------------------------------------
7636 // genPutArgStkFieldList - generate code for passing a GT_FIELD_LIST arg on the stack.
7637 //
7638 // Arguments
7639 //    treeNode      - the GT_PUTARG_STK node whose op1 is a GT_FIELD_LIST
7640 //
7641 // Return value:
7642 //    None
7643 //
7644 void CodeGen::genPutArgStkFieldList(GenTreePutArgStk* putArgStk)
7645 {
7646     GenTreeFieldList* const fieldList = putArgStk->gtOp1->AsFieldList();
7647     assert(fieldList != nullptr);
7648
7649     // Set m_pushStkArg and pre-adjust the stack if necessary.
7650     const bool preAdjustedStack = genAdjustStackForPutArgStk(putArgStk);
7651
7652     // For now, we only support the "push" case; we will push a full slot for the first field of each slot
7653     // within the struct.
7654     assert((putArgStk->isPushKind()) && !preAdjustedStack && m_pushStkArg);
7655
7656     // If we have pre-adjusted the stack and are simply storing the fields in order, set the offset to 0.
7657     // (Note that this mode is not currently being used.)
7658     // If we are pushing the arguments (i.e. we have not pre-adjusted the stack), then we are pushing them
7659     // in reverse order, so we start with the current field offset at the size of the struct arg (which must be
7660     // a multiple of the target pointer size).
7661     unsigned  currentOffset   = (preAdjustedStack) ? 0 : putArgStk->getArgSize();
7662     unsigned  prevFieldOffset = currentOffset;
7663     regNumber intTmpReg       = REG_NA;
7664     regNumber simdTmpReg      = REG_NA;
7665     if (putArgStk->AvailableTempRegCount() != 0)
7666     {
7667         regMaskTP rsvdRegs = putArgStk->gtRsvdRegs;
7668         if ((rsvdRegs & RBM_ALLINT) != 0)
7669         {
7670             intTmpReg = putArgStk->GetSingleTempReg(RBM_ALLINT);
7671             assert(genIsValidIntReg(intTmpReg));
7672         }
7673         if ((rsvdRegs & RBM_ALLFLOAT) != 0)
7674         {
7675             simdTmpReg = putArgStk->GetSingleTempReg(RBM_ALLFLOAT);
7676             assert(genIsValidFloatReg(simdTmpReg));
7677         }
7678         assert(genCountBits(rsvdRegs) == (unsigned)((intTmpReg == REG_NA) ? 0 : 1) + ((simdTmpReg == REG_NA) ? 0 : 1));
7679     }
7680
7681     for (GenTreeFieldList* current = fieldList; current != nullptr; current = current->Rest())
7682     {
7683         GenTree* const fieldNode   = current->Current();
7684         const unsigned fieldOffset = current->gtFieldOffset;
7685         var_types      fieldType   = current->gtFieldType;
7686
7687         // Long-typed nodes should have been handled by the decomposition pass, and lowering should have sorted the
7688         // field list in descending order by offset.
7689         assert(!varTypeIsLong(fieldType));
7690         assert(fieldOffset <= prevFieldOffset);
7691
7692         // Consume the register, if any, for this field. Note that genConsumeRegs() will appropriately
7693         // update the liveness info for a lclVar that has been marked RegOptional, which hasn't been
7694         // assigned a register, and which is therefore contained.
7695         // Unlike genConsumeReg(), it handles the case where no registers are being consumed.
7696         genConsumeRegs(fieldNode);
7697         regNumber argReg = fieldNode->isUsedFromSpillTemp() ? REG_NA : fieldNode->gtRegNum;
7698
7699         // If the field is slot-like, we can use a push instruction to store the entire register no matter the type.
7700         //
7701         // The GC encoder requires that the stack remain 4-byte aligned at all times. Round the adjustment up
7702         // to the next multiple of 4. If we are going to generate a `push` instruction, the adjustment must
7703         // not require rounding.
7704         // NOTE: if the field is of GC type, we must use a push instruction, since the emitter is not otherwise
7705         // able to detect stores into the outgoing argument area of the stack on x86.
7706         const bool fieldIsSlot = ((fieldOffset % 4) == 0) && ((prevFieldOffset - fieldOffset) >= 4);
7707         int        adjustment  = roundUp(currentOffset - fieldOffset, 4);
7708         if (fieldIsSlot && !varTypeIsSIMD(fieldType))
7709         {
7710             fieldType         = genActualType(fieldType);
7711             unsigned pushSize = genTypeSize(fieldType);
7712             assert((pushSize % 4) == 0);
7713             adjustment -= pushSize;
7714             while (adjustment != 0)
7715             {
7716                 inst_IV(INS_push, 0);
7717                 currentOffset -= pushSize;
7718                 AddStackLevel(pushSize);
7719                 adjustment -= pushSize;
7720             }
7721             m_pushStkArg = true;
7722         }
7723         else
7724         {
7725             m_pushStkArg = false;
7726
7727             // We always "push" floating point fields (i.e. they are full slot values that don't
7728             // require special handling).
7729             assert(varTypeIsIntegralOrI(fieldNode) || varTypeIsSIMD(fieldNode));
7730
7731             // If we can't push this field, it needs to be in a register so that we can store
7732             // it to the stack location.
7733             if (adjustment != 0)
7734             {
7735                 // This moves the stack pointer to fieldOffset.
7736                 // For this case, we must adjust the stack and generate stack-relative stores rather than pushes.
7737                 // Adjust the stack pointer to the next slot boundary.
7738                 inst_RV_IV(INS_sub, REG_SPBASE, adjustment, EA_PTRSIZE);
7739                 currentOffset -= adjustment;
7740                 AddStackLevel(adjustment);
7741             }
7742
7743             // Does it need to be in a byte register?
7744             // If so, we'll use intTmpReg, which must have been allocated as a byte register.
7745             // If it's already in a register, but not a byteable one, then move it.
7746             if (varTypeIsByte(fieldType) && ((argReg == REG_NA) || ((genRegMask(argReg) & RBM_BYTE_REGS) == 0)))
7747             {
7748                 assert(intTmpReg != REG_NA);
7749                 noway_assert((genRegMask(intTmpReg) & RBM_BYTE_REGS) != 0);
7750                 if (argReg != REG_NA)
7751                 {
7752                     inst_RV_RV(INS_mov, intTmpReg, argReg, fieldType);
7753                     argReg = intTmpReg;
7754                 }
7755             }
7756         }
7757
7758         if (argReg == REG_NA)
7759         {
7760             if (m_pushStkArg)
7761             {
7762                 if (fieldNode->isUsedFromSpillTemp())
7763                 {
7764                     assert(!varTypeIsSIMD(fieldType)); // Q: can we get here with SIMD?
7765                     assert(fieldNode->IsRegOptional());
7766                     TempDsc* tmp = getSpillTempDsc(fieldNode);
7767                     getEmitter()->emitIns_S(INS_push, emitActualTypeSize(fieldNode->TypeGet()), tmp->tdTempNum(), 0);
7768                     compiler->tmpRlsTemp(tmp);
7769                 }
7770                 else
7771                 {
7772                     assert(varTypeIsIntegralOrI(fieldNode));
7773                     switch (fieldNode->OperGet())
7774                     {
7775                         case GT_LCL_VAR:
7776                             inst_TT(INS_push, fieldNode, 0, 0, emitActualTypeSize(fieldNode->TypeGet()));
7777                             break;
7778                         case GT_CNS_INT:
7779                             if (fieldNode->IsIconHandle())
7780                             {
7781                                 inst_IV_handle(INS_push, fieldNode->gtIntCon.gtIconVal);
7782                             }
7783                             else
7784                             {
7785                                 inst_IV(INS_push, fieldNode->gtIntCon.gtIconVal);
7786                             }
7787                             break;
7788                         default:
7789                             unreached();
7790                     }
7791                 }
7792                 currentOffset -= TARGET_POINTER_SIZE;
7793                 AddStackLevel(TARGET_POINTER_SIZE);
7794             }
7795             else
7796             {
7797                 // The stack has been adjusted and we will load the field to intTmpReg and then store it on the stack.
7798                 assert(varTypeIsIntegralOrI(fieldNode));
7799                 switch (fieldNode->OperGet())
7800                 {
7801                     case GT_LCL_VAR:
7802                         inst_RV_TT(INS_mov, intTmpReg, fieldNode);
7803                         break;
7804                     case GT_CNS_INT:
7805                         genSetRegToConst(intTmpReg, fieldNode->TypeGet(), fieldNode);
7806                         break;
7807                     default:
7808                         unreached();
7809                 }
7810                 genStoreRegToStackArg(fieldType, intTmpReg, fieldOffset - currentOffset);
7811             }
7812         }
7813         else
7814         {
7815 #if defined(FEATURE_SIMD)
7816             if (fieldType == TYP_SIMD12)
7817             {
7818                 assert(genIsValidFloatReg(simdTmpReg));
7819                 genStoreSIMD12ToStack(argReg, simdTmpReg);
7820             }
7821             else
7822 #endif // defined(FEATURE_SIMD)
7823             {
7824                 genStoreRegToStackArg(fieldType, argReg, fieldOffset - currentOffset);
7825             }
7826             if (m_pushStkArg)
7827             {
7828                 // We always push a slot-rounded size
7829                 currentOffset -= genTypeSize(fieldType);
7830             }
7831         }
7832
7833         prevFieldOffset = fieldOffset;
7834     }
7835     if (currentOffset != 0)
7836     {
7837         // We don't expect padding at the beginning of a struct, but it could happen with explicit layout.
7838         inst_RV_IV(INS_sub, REG_SPBASE, currentOffset, EA_PTRSIZE);
7839         AddStackLevel(currentOffset);
7840     }
7841 }
7842 #endif // _TARGET_X86_
7843
7844 //---------------------------------------------------------------------
7845 // genPutArgStk - generate code for passing an arg on the stack.
7846 //
7847 // Arguments
7848 //    treeNode      - the GT_PUTARG_STK node
7849 //    targetType    - the type of the treeNode
7850 //
7851 // Return value:
7852 //    None
7853 //
7854 void CodeGen::genPutArgStk(GenTreePutArgStk* putArgStk)
7855 {
7856     var_types targetType = putArgStk->TypeGet();
7857
7858 #ifdef _TARGET_X86_
7859
7860     genAlignStackBeforeCall(putArgStk);
7861
7862     if (varTypeIsStruct(targetType))
7863     {
7864         (void)genAdjustStackForPutArgStk(putArgStk);
7865         genPutStructArgStk(putArgStk);
7866         return;
7867     }
7868
7869     // The following logic is applicable for x86 arch.
7870     assert(!varTypeIsFloating(targetType) || (targetType == putArgStk->gtOp1->TypeGet()));
7871
7872     GenTreePtr data = putArgStk->gtOp1;
7873
7874     // On a 32-bit target, all of the long arguments are handled with GT_FIELD_LIST,
7875     // and the type of the putArgStk is TYP_VOID.
7876     assert(targetType != TYP_LONG);
7877
7878     const unsigned argSize = putArgStk->getArgSize();
7879     assert((argSize % TARGET_POINTER_SIZE) == 0);
7880
7881     if (data->isContainedIntOrIImmed())
7882     {
7883         if (data->IsIconHandle())
7884         {
7885             inst_IV_handle(INS_push, data->gtIntCon.gtIconVal);
7886         }
7887         else
7888         {
7889             inst_IV(INS_push, data->gtIntCon.gtIconVal);
7890         }
7891         AddStackLevel(argSize);
7892     }
7893     else if (data->OperGet() == GT_FIELD_LIST)
7894     {
7895         genPutArgStkFieldList(putArgStk);
7896     }
7897     else
7898     {
7899         // We should not see any contained nodes that are not immediates.
7900         assert(data->isUsedFromReg());
7901         genConsumeReg(data);
7902         genPushReg(targetType, data->gtRegNum);
7903     }
7904 #else // !_TARGET_X86_
7905     {
7906         unsigned baseVarNum = getBaseVarForPutArgStk(putArgStk);
7907
7908 #ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
7909
7910         if (varTypeIsStruct(targetType))
7911         {
7912             m_stkArgVarNum = baseVarNum;
7913             m_stkArgOffset = putArgStk->getArgOffset();
7914             genPutStructArgStk(putArgStk);
7915             m_stkArgVarNum = BAD_VAR_NUM;
7916             return;
7917         }
7918 #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
7919
7920         noway_assert(targetType != TYP_STRUCT);
7921         assert(!varTypeIsFloating(targetType) || (targetType == putArgStk->gtOp1->TypeGet()));
7922
7923         // Get argument offset on stack.
7924         // Here we cross check that argument offset hasn't changed from lowering to codegen since
7925         // we are storing arg slot number in GT_PUTARG_STK node in lowering phase.
7926         int              argOffset      = putArgStk->getArgOffset();
7927
7928 #ifdef DEBUG
7929         fgArgTabEntryPtr curArgTabEntry = compiler->gtArgEntryByNode(putArgStk->gtCall, putArgStk);
7930         assert(curArgTabEntry);
7931         assert(argOffset == (int)curArgTabEntry->slotNum * TARGET_POINTER_SIZE);
7932 #endif
7933
7934         GenTreePtr data = putArgStk->gtOp1;
7935
7936         if (data->isContainedIntOrIImmed())
7937         {
7938             getEmitter()->emitIns_S_I(ins_Store(targetType), emitTypeSize(targetType), baseVarNum, argOffset,
7939                                       (int)data->AsIntConCommon()->IconValue());
7940         }
7941         else
7942         {
7943             assert(data->isUsedFromReg());
7944             genConsumeReg(data);
7945             getEmitter()->emitIns_S_R(ins_Store(targetType), emitTypeSize(targetType), data->gtRegNum, baseVarNum,
7946                                       argOffset);
7947         }
7948     }
7949 #endif // !_TARGET_X86_
7950 }
7951
7952 #ifdef _TARGET_X86_
7953 // genPushReg: Push a register value onto the stack and adjust the stack level
7954 //
7955 // Arguments:
7956 //    type   - the type of value to be stored
7957 //    reg    - the register containing the value
7958 //
7959 // Notes:
7960 //    For TYP_LONG, the srcReg must be a floating point register.
7961 //    Otherwise, the register type must be consistent with the given type.
7962 //
7963 void CodeGen::genPushReg(var_types type, regNumber srcReg)
7964 {
7965     unsigned size = genTypeSize(type);
7966     if (varTypeIsIntegralOrI(type) && type != TYP_LONG)
7967     {
7968         assert(genIsValidIntReg(srcReg));
7969         inst_RV(INS_push, srcReg, type);
7970     }
7971     else
7972     {
7973         instruction ins;
7974         emitAttr    attr = emitTypeSize(type);
7975         if (type == TYP_LONG)
7976         {
7977             // On x86, the only way we can push a TYP_LONG from a register is if it is in an xmm reg.
7978             // This is only used when we are pushing a struct from memory to memory, and basically is
7979             // handling an 8-byte "chunk", as opposed to strictly a long type.
7980             ins = INS_movq;
7981         }
7982         else
7983         {
7984             ins = ins_Store(type);
7985         }
7986         assert(genIsValidFloatReg(srcReg));
7987         inst_RV_IV(INS_sub, REG_SPBASE, size, EA_PTRSIZE);
7988         getEmitter()->emitIns_AR_R(ins, attr, srcReg, REG_SPBASE, 0);
7989     }
7990     AddStackLevel(size);
7991 }
7992 #endif // _TARGET_X86_
7993
7994 #if defined(FEATURE_PUT_STRUCT_ARG_STK)
7995 // genStoreRegToStackArg: Store a register value into the stack argument area
7996 //
7997 // Arguments:
7998 //    type   - the type of value to be stored
7999 //    reg    - the register containing the value
8000 //    offset - the offset from the base (see Assumptions below)
8001 //
8002 // Notes:
8003 //    A type of TYP_STRUCT instructs this method to store a 16-byte chunk
8004 //    at the given offset (i.e. not the full struct).
8005 //
8006 // Assumptions:
8007 //    The caller must set the context appropriately before calling this method:
8008 //    - On x64, m_stkArgVarNum must be set according to whether this is a regular or tail call.
8009 //    - On x86, the caller must set m_pushStkArg if this method should push the argument.
8010 //      Otherwise, the argument is stored at the given offset from sp.
8011 //
8012 // TODO: In the below code the load and store instructions are for 16 bytes, but the
8013 //          type is EA_8BYTE. The movdqa/u are 16 byte instructions, so it works, but
8014 //          this probably needs to be changed.
8015 //
8016 void CodeGen::genStoreRegToStackArg(var_types type, regNumber srcReg, int offset)
8017 {
8018     assert(srcReg != REG_NA);
8019     instruction ins;
8020     emitAttr    attr;
8021     unsigned    size;
8022
8023     if (type == TYP_STRUCT)
8024     {
8025         ins = INS_movdqu;
8026         // This should be changed!
8027         attr = EA_8BYTE;
8028         size = 16;
8029     }
8030     else
8031     {
8032 #ifdef FEATURE_SIMD
8033         if (varTypeIsSIMD(type))
8034         {
8035             assert(genIsValidFloatReg(srcReg));
8036             ins = ins_Store(type); // TODO-CQ: pass 'aligned' correctly
8037         }
8038         else
8039 #endif // FEATURE_SIMD
8040 #ifdef _TARGET_X86_
8041             if (type == TYP_LONG)
8042         {
8043             assert(genIsValidFloatReg(srcReg));
8044             ins = INS_movq;
8045         }
8046         else
8047 #endif // _TARGET_X86_
8048         {
8049             assert((varTypeIsFloating(type) && genIsValidFloatReg(srcReg)) ||
8050                    (varTypeIsIntegralOrI(type) && genIsValidIntReg(srcReg)));
8051             ins = ins_Store(type);
8052         }
8053         attr = emitTypeSize(type);
8054         size = genTypeSize(type);
8055     }
8056
8057 #ifdef _TARGET_X86_
8058     if (m_pushStkArg)
8059     {
8060         genPushReg(type, srcReg);
8061     }
8062     else
8063     {
8064         getEmitter()->emitIns_AR_R(ins, attr, srcReg, REG_SPBASE, offset);
8065     }
8066 #else  // !_TARGET_X86_
8067     assert(m_stkArgVarNum != BAD_VAR_NUM);
8068     getEmitter()->emitIns_S_R(ins, attr, srcReg, m_stkArgVarNum, m_stkArgOffset + offset);
8069 #endif // !_TARGET_X86_
8070 }
8071
8072 //---------------------------------------------------------------------
8073 // genPutStructArgStk - generate code for copying a struct arg on the stack by value.
8074 //                In case there are references to heap object in the struct,
8075 //                it generates the gcinfo as well.
8076 //
8077 // Arguments
8078 //    putArgStk - the GT_PUTARG_STK node
8079 //
8080 // Notes:
8081 //    In the case of fixed out args, the caller must have set m_stkArgVarNum to the variable number
8082 //    corresponding to the argument area (where we will put the argument on the stack).
8083 //    For tail calls this is the baseVarNum = 0.
8084 //    For non tail calls this is the outgoingArgSpace.
8085 void CodeGen::genPutStructArgStk(GenTreePutArgStk* putArgStk)
8086 {
8087     var_types targetType = putArgStk->TypeGet();
8088
8089 #if defined(_TARGET_X86_) && defined(FEATURE_SIMD)
8090     if (targetType == TYP_SIMD12)
8091     {
8092         genPutArgStkSIMD12(putArgStk);
8093         return;
8094     }
8095 #endif // defined(_TARGET_X86_) && defined(FEATURE_SIMD)
8096
8097     if (varTypeIsSIMD(targetType))
8098     {
8099         regNumber srcReg = genConsumeReg(putArgStk->gtGetOp1());
8100         assert((srcReg != REG_NA) && (genIsValidFloatReg(srcReg)));
8101         genStoreRegToStackArg(targetType, srcReg, 0);
8102         return;
8103     }
8104
8105     assert(targetType == TYP_STRUCT);
8106
8107     if (putArgStk->gtNumberReferenceSlots == 0)
8108     {
8109         switch (putArgStk->gtPutArgStkKind)
8110         {
8111             case GenTreePutArgStk::Kind::RepInstr:
8112                 genStructPutArgRepMovs(putArgStk);
8113                 break;
8114             case GenTreePutArgStk::Kind::Unroll:
8115                 genStructPutArgUnroll(putArgStk);
8116                 break;
8117             case GenTreePutArgStk::Kind::Push:
8118                 genStructPutArgUnroll(putArgStk);
8119                 break;
8120             default:
8121                 unreached();
8122         }
8123     }
8124     else
8125     {
8126         // No need to disable GC the way COPYOBJ does. Here the refs are copied in atomic operations always.
8127         CLANG_FORMAT_COMMENT_ANCHOR;
8128
8129 #ifdef _TARGET_X86_
8130         // On x86, any struct that has contains GC references must be stored to the stack using `push` instructions so
8131         // that the emitter properly detects the need to update the method's GC information.
8132         //
8133         // Strictly speaking, it is only necessary to use `push` to store the GC references themselves, so for structs
8134         // with large numbers of consecutive non-GC-ref-typed fields, we may be able to improve the code size in the
8135         // future.
8136         assert(m_pushStkArg);
8137
8138         GenTree*       srcAddr  = putArgStk->gtGetOp1()->gtGetOp1();
8139         BYTE*          gcPtrs   = putArgStk->gtGcPtrs;
8140         const unsigned numSlots = putArgStk->gtNumSlots;
8141
8142         regNumber  srcRegNum    = srcAddr->gtRegNum;
8143         const bool srcAddrInReg = srcRegNum != REG_NA;
8144
8145         unsigned srcLclNum    = 0;
8146         unsigned srcLclOffset = 0;
8147         if (srcAddrInReg)
8148         {
8149             genConsumeReg(srcAddr);
8150         }
8151         else
8152         {
8153             assert(srcAddr->OperIsLocalAddr());
8154
8155             srcLclNum = srcAddr->AsLclVarCommon()->gtLclNum;
8156             if (srcAddr->OperGet() == GT_LCL_FLD_ADDR)
8157             {
8158                 srcLclOffset = srcAddr->AsLclFld()->gtLclOffs;
8159             }
8160         }
8161
8162         for (int i = numSlots - 1; i >= 0; --i)
8163         {
8164             emitAttr slotAttr;
8165             if (gcPtrs[i] == TYPE_GC_NONE)
8166             {
8167                 slotAttr = EA_4BYTE;
8168             }
8169             else if (gcPtrs[i] == TYPE_GC_REF)
8170             {
8171                 slotAttr = EA_GCREF;
8172             }
8173             else
8174             {
8175                 assert(gcPtrs[i] == TYPE_GC_BYREF);
8176                 slotAttr = EA_BYREF;
8177             }
8178
8179             const unsigned offset = i * TARGET_POINTER_SIZE;
8180             if (srcAddrInReg)
8181             {
8182                 getEmitter()->emitIns_AR_R(INS_push, slotAttr, REG_NA, srcRegNum, offset);
8183             }
8184             else
8185             {
8186                 getEmitter()->emitIns_S(INS_push, slotAttr, srcLclNum, srcLclOffset + offset);
8187             }
8188             AddStackLevel(TARGET_POINTER_SIZE);
8189         }
8190 #else // !defined(_TARGET_X86_)
8191
8192         // Consume these registers.
8193         // They may now contain gc pointers (depending on their type; gcMarkRegPtrVal will "do the right thing").
8194         genConsumePutStructArgStk(putArgStk, REG_RDI, REG_RSI, REG_NA);
8195
8196         const bool     srcIsLocal       = putArgStk->gtOp1->AsObj()->gtOp1->OperIsLocalAddr();
8197         const emitAttr srcAddrAttr      = srcIsLocal ? EA_PTRSIZE : EA_BYREF;
8198
8199 #if DEBUG
8200         unsigned       numGCSlotsCopied = 0;
8201 #endif // DEBUG
8202
8203         BYTE*          gcPtrs   = putArgStk->gtGcPtrs;
8204         const unsigned numSlots = putArgStk->gtNumSlots;
8205         for (unsigned i = 0; i < numSlots;)
8206         {
8207             if (gcPtrs[i] == TYPE_GC_NONE)
8208             {
8209                 // Let's see if we can use rep movsp (alias for movsd or movsq for 32 and 64 bits respectively)
8210                 // instead of a sequence of movsp instructions to save cycles and code size.
8211                 unsigned adjacentNonGCSlotCount = 0;
8212                 do
8213                 {
8214                     adjacentNonGCSlotCount++;
8215                     i++;
8216                 } while ((i < numSlots) && (gcPtrs[i] == TYPE_GC_NONE));
8217
8218                 // If we have a very small contiguous non-ref region, it's better just to
8219                 // emit a sequence of movsp instructions
8220                 if (adjacentNonGCSlotCount < CPOBJ_NONGC_SLOTS_LIMIT)
8221                 {
8222                     for (; adjacentNonGCSlotCount > 0; adjacentNonGCSlotCount--)
8223                     {
8224                         instGen(INS_movsp);
8225                     }
8226                 }
8227                 else
8228                 {
8229                     getEmitter()->emitIns_R_I(INS_mov, EA_4BYTE, REG_RCX, adjacentNonGCSlotCount);
8230                     instGen(INS_r_movsp);
8231                 }
8232             }
8233             else
8234             {
8235                 assert((gcPtrs[i] == TYPE_GC_REF) || (gcPtrs[i] == TYPE_GC_BYREF));
8236
8237                 // We have a GC (byref or ref) pointer
8238                 // TODO-Amd64-Unix: Here a better solution (for code size and CQ) would be to use movsp instruction,
8239                 // but the logic for emitting a GC info record is not available (it is internal for the emitter
8240                 // only.) See emitGCVarLiveUpd function. If we could call it separately, we could do
8241                 // instGen(INS_movsp); and emission of gc info.
8242
8243                 var_types memType = (gcPtrs[i] == TYPE_GC_REF) ? TYP_REF : TYP_BYREF;
8244                 getEmitter()->emitIns_R_AR(ins_Load(memType), emitTypeSize(memType), REG_RCX, REG_RSI, 0);
8245                 genStoreRegToStackArg(memType, REG_RCX, i * TARGET_POINTER_SIZE);
8246
8247 #ifdef DEBUG
8248                 numGCSlotsCopied++;
8249 #endif // DEBUG
8250
8251                 i++;
8252                 if (i < numSlots)
8253                 {
8254                     // Source for the copy operation.
8255                     // If a LocalAddr, use EA_PTRSIZE - copy from stack.
8256                     // If not a LocalAddr, use EA_BYREF - the source location is not on the stack.
8257                     getEmitter()->emitIns_R_I(INS_add, srcAddrAttr, REG_RSI, TARGET_POINTER_SIZE);
8258
8259                     // Always copying to the stack - outgoing arg area
8260                     // (or the outgoing arg area of the caller for a tail call) - use EA_PTRSIZE.
8261                     getEmitter()->emitIns_R_I(INS_add, EA_PTRSIZE, REG_RDI, TARGET_POINTER_SIZE);
8262                 }
8263             }
8264         }
8265
8266         assert(numGCSlotsCopied == putArgStk->gtNumberReferenceSlots);
8267 #endif // _TARGET_X86_
8268     }
8269 }
8270 #endif // defined(FEATURE_PUT_STRUCT_ARG_STK)
8271
8272 /*****************************************************************************
8273  *
8274  *  Create and record GC Info for the function.
8275  */
8276 #ifndef JIT32_GCENCODER
8277 void
8278 #else  // !JIT32_GCENCODER
8279 void*
8280 #endif // !JIT32_GCENCODER
8281 CodeGen::genCreateAndStoreGCInfo(unsigned codeSize, unsigned prologSize, unsigned epilogSize DEBUGARG(void* codePtr))
8282 {
8283 #ifdef JIT32_GCENCODER
8284     return genCreateAndStoreGCInfoJIT32(codeSize, prologSize, epilogSize DEBUGARG(codePtr));
8285 #else  // !JIT32_GCENCODER
8286     genCreateAndStoreGCInfoX64(codeSize, prologSize DEBUGARG(codePtr));
8287 #endif // !JIT32_GCENCODER
8288 }
8289
8290 #ifdef JIT32_GCENCODER
8291 void* CodeGen::genCreateAndStoreGCInfoJIT32(unsigned codeSize,
8292                                             unsigned prologSize,
8293                                             unsigned epilogSize DEBUGARG(void* codePtr))
8294 {
8295     BYTE    headerBuf[64];
8296     InfoHdr header;
8297
8298     int s_cached;
8299 #ifdef DEBUG
8300     size_t headerSize =
8301 #endif
8302         compiler->compInfoBlkSize =
8303             gcInfo.gcInfoBlockHdrSave(headerBuf, 0, codeSize, prologSize, epilogSize, &header, &s_cached);
8304
8305     size_t argTabOffset = 0;
8306     size_t ptrMapSize   = gcInfo.gcPtrTableSize(header, codeSize, &argTabOffset);
8307
8308 #if DISPLAY_SIZES
8309
8310     if (genInterruptible)
8311     {
8312         gcHeaderISize += compiler->compInfoBlkSize;
8313         gcPtrMapISize += ptrMapSize;
8314     }
8315     else
8316     {
8317         gcHeaderNSize += compiler->compInfoBlkSize;
8318         gcPtrMapNSize += ptrMapSize;
8319     }
8320
8321 #endif // DISPLAY_SIZES
8322
8323     compiler->compInfoBlkSize += ptrMapSize;
8324
8325     /* Allocate the info block for the method */
8326
8327     compiler->compInfoBlkAddr = (BYTE*)compiler->info.compCompHnd->allocGCInfo(compiler->compInfoBlkSize);
8328
8329 #if 0 // VERBOSE_SIZES
8330     // TODO-X86-Cleanup: 'dataSize', below, is not defined
8331
8332 //  if  (compiler->compInfoBlkSize > codeSize && compiler->compInfoBlkSize > 100)
8333     {
8334         printf("[%7u VM, %7u+%7u/%7u x86 %03u/%03u%%] %s.%s\n",
8335                compiler->info.compILCodeSize,
8336                compiler->compInfoBlkSize,
8337                codeSize + dataSize,
8338                codeSize + dataSize - prologSize - epilogSize,
8339                100 * (codeSize + dataSize) / compiler->info.compILCodeSize,
8340                100 * (codeSize + dataSize + compiler->compInfoBlkSize) / compiler->info.compILCodeSize,
8341                compiler->info.compClassName,
8342                compiler->info.compMethodName);
8343 }
8344
8345 #endif
8346
8347     /* Fill in the info block and return it to the caller */
8348
8349     void* infoPtr = compiler->compInfoBlkAddr;
8350
8351     /* Create the method info block: header followed by GC tracking tables */
8352
8353     compiler->compInfoBlkAddr +=
8354         gcInfo.gcInfoBlockHdrSave(compiler->compInfoBlkAddr, -1, codeSize, prologSize, epilogSize, &header, &s_cached);
8355
8356     assert(compiler->compInfoBlkAddr == (BYTE*)infoPtr + headerSize);
8357     compiler->compInfoBlkAddr = gcInfo.gcPtrTableSave(compiler->compInfoBlkAddr, header, codeSize, &argTabOffset);
8358     assert(compiler->compInfoBlkAddr == (BYTE*)infoPtr + headerSize + ptrMapSize);
8359
8360 #ifdef DEBUG
8361
8362     if (0)
8363     {
8364         BYTE*    temp = (BYTE*)infoPtr;
8365         unsigned size = compiler->compInfoBlkAddr - temp;
8366         BYTE*    ptab = temp + headerSize;
8367
8368         noway_assert(size == headerSize + ptrMapSize);
8369
8370         printf("Method info block - header [%u bytes]:", headerSize);
8371
8372         for (unsigned i = 0; i < size; i++)
8373         {
8374             if (temp == ptab)
8375             {
8376                 printf("\nMethod info block - ptrtab [%u bytes]:", ptrMapSize);
8377                 printf("\n    %04X: %*c", i & ~0xF, 3 * (i & 0xF), ' ');
8378             }
8379             else
8380             {
8381                 if (!(i % 16))
8382                     printf("\n    %04X: ", i);
8383             }
8384
8385             printf("%02X ", *temp++);
8386         }
8387
8388         printf("\n");
8389     }
8390
8391 #endif // DEBUG
8392
8393 #if DUMP_GC_TABLES
8394
8395     if (compiler->opts.dspGCtbls)
8396     {
8397         const BYTE* base = (BYTE*)infoPtr;
8398         unsigned    size;
8399         unsigned    methodSize;
8400         InfoHdr     dumpHeader;
8401
8402         printf("GC Info for method %s\n", compiler->info.compFullName);
8403         printf("GC info size = %3u\n", compiler->compInfoBlkSize);
8404
8405         size = gcInfo.gcInfoBlockHdrDump(base, &dumpHeader, &methodSize);
8406         // printf("size of header encoding is %3u\n", size);
8407         printf("\n");
8408
8409         if (compiler->opts.dspGCtbls)
8410         {
8411             base += size;
8412             size = gcInfo.gcDumpPtrTable(base, dumpHeader, methodSize);
8413             // printf("size of pointer table is %3u\n", size);
8414             printf("\n");
8415             noway_assert(compiler->compInfoBlkAddr == (base + size));
8416         }
8417     }
8418
8419 #ifdef DEBUG
8420     if (jitOpts.testMask & 128)
8421     {
8422         for (unsigned offs = 0; offs < codeSize; offs++)
8423         {
8424             gcInfo.gcFindPtrsInFrame(infoPtr, codePtr, offs);
8425         }
8426     }
8427 #endif // DEBUG
8428 #endif // DUMP_GC_TABLES
8429
8430     /* Make sure we ended up generating the expected number of bytes */
8431
8432     noway_assert(compiler->compInfoBlkAddr == (BYTE*)infoPtr + compiler->compInfoBlkSize);
8433
8434     return infoPtr;
8435 }
8436
8437 #else  // !JIT32_GCENCODER
8438 void CodeGen::genCreateAndStoreGCInfoX64(unsigned codeSize, unsigned prologSize DEBUGARG(void* codePtr))
8439 {
8440     IAllocator*    allowZeroAlloc = new (compiler, CMK_GC) AllowZeroAllocator(compiler->getAllocatorGC());
8441     GcInfoEncoder* gcInfoEncoder  = new (compiler, CMK_GC)
8442         GcInfoEncoder(compiler->info.compCompHnd, compiler->info.compMethodInfo, allowZeroAlloc, NOMEM);
8443     assert(gcInfoEncoder);
8444
8445     // Follow the code pattern of the x86 gc info encoder (genCreateAndStoreGCInfoJIT32).
8446     gcInfo.gcInfoBlockHdrSave(gcInfoEncoder, codeSize, prologSize);
8447
8448     // We keep the call count for the second call to gcMakeRegPtrTable() below.
8449     unsigned callCnt = 0;
8450     // First we figure out the encoder ID's for the stack slots and registers.
8451     gcInfo.gcMakeRegPtrTable(gcInfoEncoder, codeSize, prologSize, GCInfo::MAKE_REG_PTR_MODE_ASSIGN_SLOTS, &callCnt);
8452     // Now we've requested all the slots we'll need; "finalize" these (make more compact data structures for them).
8453     gcInfoEncoder->FinalizeSlotIds();
8454     // Now we can actually use those slot ID's to declare live ranges.
8455     gcInfo.gcMakeRegPtrTable(gcInfoEncoder, codeSize, prologSize, GCInfo::MAKE_REG_PTR_MODE_DO_WORK, &callCnt);
8456
8457     if (compiler->opts.compDbgEnC)
8458     {
8459         // what we have to preserve is called the "frame header" (see comments in VM\eetwain.cpp)
8460         // which is:
8461         //  -return address
8462         //  -saved off RBP
8463         //  -saved 'this' pointer and bool for synchronized methods
8464
8465         // 4 slots for RBP + return address + RSI + RDI
8466         int preservedAreaSize = 4 * REGSIZE_BYTES;
8467
8468         if (compiler->info.compFlags & CORINFO_FLG_SYNCH)
8469         {
8470             if (!(compiler->info.compFlags & CORINFO_FLG_STATIC))
8471             {
8472                 preservedAreaSize += REGSIZE_BYTES;
8473             }
8474
8475             // bool in synchronized methods that tracks whether the lock has been taken (takes 4 bytes on stack)
8476             preservedAreaSize += 4;
8477         }
8478
8479         // Used to signal both that the method is compiled for EnC, and also the size of the block at the top of the
8480         // frame
8481         gcInfoEncoder->SetSizeOfEditAndContinuePreservedArea(preservedAreaSize);
8482     }
8483
8484     if (compiler->opts.IsReversePInvoke())
8485     {
8486         unsigned reversePInvokeFrameVarNumber = compiler->lvaReversePInvokeFrameVar;
8487         assert(reversePInvokeFrameVarNumber != BAD_VAR_NUM && reversePInvokeFrameVarNumber < compiler->lvaRefCount);
8488         LclVarDsc& reversePInvokeFrameVar = compiler->lvaTable[reversePInvokeFrameVarNumber];
8489         gcInfoEncoder->SetReversePInvokeFrameSlot(reversePInvokeFrameVar.lvStkOffs);
8490     }
8491
8492     gcInfoEncoder->Build();
8493
8494     // GC Encoder automatically puts the GC info in the right spot using ICorJitInfo::allocGCInfo(size_t)
8495     // let's save the values anyway for debugging purposes
8496     compiler->compInfoBlkAddr = gcInfoEncoder->Emit();
8497     compiler->compInfoBlkSize = 0; // not exposed by the GCEncoder interface
8498 }
8499 #endif // !JIT32_GCENCODER
8500
8501 /*****************************************************************************
8502  *  Emit a call to a helper function.
8503  *
8504  */
8505
8506 void CodeGen::genEmitHelperCall(unsigned helper, int argSize, emitAttr retSize, regNumber callTargetReg)
8507 {
8508     void* addr  = nullptr;
8509     void* pAddr = nullptr;
8510
8511     emitter::EmitCallType callType = emitter::EC_FUNC_TOKEN;
8512     addr                           = compiler->compGetHelperFtn((CorInfoHelpFunc)helper, &pAddr);
8513     regNumber callTarget           = REG_NA;
8514     regMaskTP killMask             = compiler->compHelperCallKillSet((CorInfoHelpFunc)helper);
8515
8516     if (!addr)
8517     {
8518         assert(pAddr != nullptr);
8519
8520         // Absolute indirect call addr
8521         // Note: Order of checks is important. First always check for pc-relative and next
8522         // zero-relative.  Because the former encoding is 1-byte smaller than the latter.
8523         if (genCodeIndirAddrCanBeEncodedAsPCRelOffset((size_t)pAddr) ||
8524             genCodeIndirAddrCanBeEncodedAsZeroRelOffset((size_t)pAddr))
8525         {
8526             // generate call whose target is specified by 32-bit offset relative to PC or zero.
8527             callType = emitter::EC_FUNC_TOKEN_INDIR;
8528             addr     = pAddr;
8529         }
8530         else
8531         {
8532 #ifdef _TARGET_AMD64_
8533             // If this indirect address cannot be encoded as 32-bit offset relative to PC or Zero,
8534             // load it into REG_HELPER_CALL_TARGET and use register indirect addressing mode to
8535             // make the call.
8536             //    mov   reg, addr
8537             //    call  [reg]
8538
8539             if (callTargetReg == REG_NA)
8540             {
8541                 // If a callTargetReg has not been explicitly provided, we will use REG_DEFAULT_HELPER_CALL_TARGET, but
8542                 // this is only a valid assumption if the helper call is known to kill REG_DEFAULT_HELPER_CALL_TARGET.
8543                 callTargetReg            = REG_DEFAULT_HELPER_CALL_TARGET;
8544                 regMaskTP callTargetMask = genRegMask(callTargetReg);
8545                 noway_assert((callTargetMask & killMask) == callTargetMask);
8546             }
8547             else
8548             {
8549                 // The call target must not overwrite any live variable, though it may not be in the
8550                 // kill set for the call.
8551                 regMaskTP callTargetMask = genRegMask(callTargetReg);
8552                 noway_assert((callTargetMask & regSet.rsMaskVars) == RBM_NONE);
8553             }
8554 #endif
8555
8556             callTarget = callTargetReg;
8557             CodeGen::genSetRegToIcon(callTarget, (ssize_t)pAddr, TYP_I_IMPL);
8558             callType = emitter::EC_INDIR_ARD;
8559         }
8560     }
8561
8562     // clang-format off
8563     getEmitter()->emitIns_Call(callType,
8564                                compiler->eeFindHelper(helper),
8565                                INDEBUG_LDISASM_COMMA(nullptr) addr,
8566                                argSize,
8567                                retSize
8568                                MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(EA_UNKNOWN),
8569                                gcInfo.gcVarPtrSetCur,
8570                                gcInfo.gcRegGCrefSetCur,
8571                                gcInfo.gcRegByrefSetCur,
8572                                BAD_IL_OFFSET, // IL offset
8573                                callTarget,    // ireg
8574                                REG_NA, 0, 0,  // xreg, xmul, disp
8575                                false,         // isJump
8576                                emitter::emitNoGChelper(helper));
8577     // clang-format on
8578
8579     regTracker.rsTrashRegSet(killMask);
8580     regTracker.rsTrashRegsForGCInterruptability();
8581 }
8582
8583 #if !defined(_TARGET_64BIT_)
8584 //-----------------------------------------------------------------------------
8585 //
8586 // Code Generation for Long integers
8587 //
8588 //-----------------------------------------------------------------------------
8589
8590 //------------------------------------------------------------------------
8591 // genStoreLongLclVar: Generate code to store a non-enregistered long lclVar
8592 //
8593 // Arguments:
8594 //    treeNode - A TYP_LONG lclVar node.
8595 //
8596 // Return Value:
8597 //    None.
8598 //
8599 // Assumptions:
8600 //    'treeNode' must be a TYP_LONG lclVar node for a lclVar that has NOT been promoted.
8601 //    Its operand must be a GT_LONG node.
8602 //
8603 void CodeGen::genStoreLongLclVar(GenTree* treeNode)
8604 {
8605     emitter* emit = getEmitter();
8606
8607     GenTreeLclVarCommon* lclNode = treeNode->AsLclVarCommon();
8608     unsigned             lclNum  = lclNode->gtLclNum;
8609     LclVarDsc*           varDsc  = &(compiler->lvaTable[lclNum]);
8610     assert(varDsc->TypeGet() == TYP_LONG);
8611     assert(!varDsc->lvPromoted);
8612     GenTreePtr op1 = treeNode->gtOp.gtOp1;
8613     noway_assert(op1->OperGet() == GT_LONG || op1->OperGet() == GT_MUL_LONG);
8614     genConsumeRegs(op1);
8615
8616     if (op1->OperGet() == GT_LONG)
8617     {
8618         // Definitions of register candidates will have been lowered to 2 int lclVars.
8619         assert(!treeNode->InReg());
8620
8621         GenTreePtr loVal = op1->gtGetOp1();
8622         GenTreePtr hiVal = op1->gtGetOp2();
8623
8624         // NYI: Contained immediates.
8625         NYI_IF((loVal->gtRegNum == REG_NA) || (hiVal->gtRegNum == REG_NA),
8626                "Store of long lclVar with contained immediate");
8627
8628         emit->emitIns_S_R(ins_Store(TYP_INT), EA_4BYTE, loVal->gtRegNum, lclNum, 0);
8629         emit->emitIns_S_R(ins_Store(TYP_INT), EA_4BYTE, hiVal->gtRegNum, lclNum, genTypeSize(TYP_INT));
8630     }
8631     else if (op1->OperGet() == GT_MUL_LONG)
8632     {
8633         assert((op1->gtFlags & GTF_MUL_64RSLT) != 0);
8634
8635         // Stack store
8636         getEmitter()->emitIns_S_R(ins_Store(TYP_INT), emitTypeSize(TYP_INT), REG_LNGRET_LO, lclNum, 0);
8637         getEmitter()->emitIns_S_R(ins_Store(TYP_INT), emitTypeSize(TYP_INT), REG_LNGRET_HI, lclNum,
8638                                   genTypeSize(TYP_INT));
8639     }
8640 }
8641 #endif // !defined(_TARGET_64BIT_)
8642
8643 /*****************************************************************************
8644 * Unit testing of the XArch emitter: generate a bunch of instructions into the prolog
8645 * (it's as good a place as any), then use COMPlus_JitLateDisasm=* to see if the late
8646 * disassembler thinks the instructions as the same as we do.
8647 */
8648
8649 // Uncomment "#define ALL_ARM64_EMITTER_UNIT_TESTS" to run all the unit tests here.
8650 // After adding a unit test, and verifying it works, put it under this #ifdef, so we don't see it run every time.
8651 //#define ALL_XARCH_EMITTER_UNIT_TESTS
8652
8653 #if defined(DEBUG) && defined(LATE_DISASM) && defined(_TARGET_AMD64_)
8654 void CodeGen::genAmd64EmitterUnitTests()
8655 {
8656     if (!verbose)
8657     {
8658         return;
8659     }
8660
8661     if (!compiler->opts.altJit)
8662     {
8663         // No point doing this in a "real" JIT.
8664         return;
8665     }
8666
8667     // Mark the "fake" instructions in the output.
8668     printf("*************** In genAmd64EmitterUnitTests()\n");
8669
8670     // We use this:
8671     //      genDefineTempLabel(genCreateTempLabel());
8672     // to create artificial labels to help separate groups of tests.
8673
8674     //
8675     // Loads
8676     //
8677     CLANG_FORMAT_COMMENT_ANCHOR;
8678
8679 #ifdef ALL_XARCH_EMITTER_UNIT_TESTS
8680 #ifdef FEATURE_AVX_SUPPORT
8681     genDefineTempLabel(genCreateTempLabel());
8682
8683     // vhaddpd     ymm0,ymm1,ymm2
8684     getEmitter()->emitIns_R_R_R(INS_haddpd, EA_32BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8685     // vaddss      xmm0,xmm1,xmm2
8686     getEmitter()->emitIns_R_R_R(INS_addss, EA_4BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8687     // vaddsd      xmm0,xmm1,xmm2
8688     getEmitter()->emitIns_R_R_R(INS_addsd, EA_8BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8689     // vaddps      xmm0,xmm1,xmm2
8690     getEmitter()->emitIns_R_R_R(INS_addps, EA_16BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8691     // vaddps      ymm0,ymm1,ymm2
8692     getEmitter()->emitIns_R_R_R(INS_addps, EA_32BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8693     // vaddpd      xmm0,xmm1,xmm2
8694     getEmitter()->emitIns_R_R_R(INS_addpd, EA_16BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8695     // vaddpd      ymm0,ymm1,ymm2
8696     getEmitter()->emitIns_R_R_R(INS_addpd, EA_32BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8697     // vsubss      xmm0,xmm1,xmm2
8698     getEmitter()->emitIns_R_R_R(INS_subss, EA_4BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8699     // vsubsd      xmm0,xmm1,xmm2
8700     getEmitter()->emitIns_R_R_R(INS_subsd, EA_8BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8701     // vsubps      ymm0,ymm1,ymm2
8702     getEmitter()->emitIns_R_R_R(INS_subps, EA_16BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8703     // vsubps      ymm0,ymm1,ymm2
8704     getEmitter()->emitIns_R_R_R(INS_subps, EA_32BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8705     // vsubpd      xmm0,xmm1,xmm2
8706     getEmitter()->emitIns_R_R_R(INS_subpd, EA_16BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8707     // vsubpd      ymm0,ymm1,ymm2
8708     getEmitter()->emitIns_R_R_R(INS_subpd, EA_32BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8709     // vmulss      xmm0,xmm1,xmm2
8710     getEmitter()->emitIns_R_R_R(INS_mulss, EA_4BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8711     // vmulsd      xmm0,xmm1,xmm2
8712     getEmitter()->emitIns_R_R_R(INS_mulsd, EA_8BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8713     // vmulps      xmm0,xmm1,xmm2
8714     getEmitter()->emitIns_R_R_R(INS_mulps, EA_16BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8715     // vmulpd      xmm0,xmm1,xmm2
8716     getEmitter()->emitIns_R_R_R(INS_mulpd, EA_16BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8717     // vmulps      ymm0,ymm1,ymm2
8718     getEmitter()->emitIns_R_R_R(INS_mulps, EA_32BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8719     // vmulpd      ymm0,ymm1,ymm2
8720     getEmitter()->emitIns_R_R_R(INS_mulpd, EA_32BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8721     // vandps      xmm0,xmm1,xmm2
8722     getEmitter()->emitIns_R_R_R(INS_andps, EA_16BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8723     // vandpd      xmm0,xmm1,xmm2
8724     getEmitter()->emitIns_R_R_R(INS_andpd, EA_16BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8725     // vandps      ymm0,ymm1,ymm2
8726     getEmitter()->emitIns_R_R_R(INS_andps, EA_32BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8727     // vandpd      ymm0,ymm1,ymm2
8728     getEmitter()->emitIns_R_R_R(INS_andpd, EA_32BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8729     // vorps      xmm0,xmm1,xmm2
8730     getEmitter()->emitIns_R_R_R(INS_orps, EA_16BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8731     // vorpd      xmm0,xmm1,xmm2
8732     getEmitter()->emitIns_R_R_R(INS_orpd, EA_16BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8733     // vorps      ymm0,ymm1,ymm2
8734     getEmitter()->emitIns_R_R_R(INS_orps, EA_32BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8735     // vorpd      ymm0,ymm1,ymm2
8736     getEmitter()->emitIns_R_R_R(INS_orpd, EA_32BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8737     // vdivss      xmm0,xmm1,xmm2
8738     getEmitter()->emitIns_R_R_R(INS_divss, EA_4BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8739     // vdivsd      xmm0,xmm1,xmm2
8740     getEmitter()->emitIns_R_R_R(INS_divsd, EA_8BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8741     // vdivss      xmm0,xmm1,xmm2
8742     getEmitter()->emitIns_R_R_R(INS_divss, EA_4BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8743     // vdivsd      xmm0,xmm1,xmm2
8744     getEmitter()->emitIns_R_R_R(INS_divsd, EA_8BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8745
8746     // vdivss      xmm0,xmm1,xmm2
8747     getEmitter()->emitIns_R_R_R(INS_cvtss2sd, EA_4BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8748     // vdivsd      xmm0,xmm1,xmm2
8749     getEmitter()->emitIns_R_R_R(INS_cvtsd2ss, EA_8BYTE, REG_XMM0, REG_XMM1, REG_XMM2);
8750 #endif // FEATURE_AVX_SUPPORT
8751 #endif // ALL_XARCH_EMITTER_UNIT_TESTS
8752     printf("*************** End of genAmd64EmitterUnitTests()\n");
8753 }
8754
8755 #endif // defined(DEBUG) && defined(LATE_DISASM) && defined(_TARGET_AMD64_)
8756
8757 #endif // _TARGET_AMD64_
8758
8759 #endif // !LEGACY_BACKEND