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