@@ -3783,7 +3783,8 @@ void CodeGen::genFnPrologCalleeRegArgs(regNumber xtraReg, bool* pXtraRegClobbere
37833783
37843784 varNum = regArgTab[argNum].varNum ;
37853785 noway_assert (varNum < compiler->lvaCount );
3786- varDsc = compiler->lvaTable + varNum;
3786+ varDsc = compiler->lvaTable + varNum;
3787+ const var_types varRegType = varDsc->GetRegisterType ();
37873788 noway_assert (varDsc->lvIsParam && varDsc->lvIsRegArg );
37883789
37893790 /* cannot possibly have stack arguments */
@@ -3827,7 +3828,7 @@ void CodeGen::genFnPrologCalleeRegArgs(regNumber xtraReg, bool* pXtraRegClobbere
38273828 assert (argNum > 0 );
38283829 assert (regArgTab[argNum - 1 ].slot == 1 );
38293830 assert (regArgTab[argNum - 1 ].varNum == varNum);
3830- assert ((varDsc-> lvType == TYP_SIMD12) || (varDsc-> lvType == TYP_SIMD16));
3831+ assert ((varRegType == TYP_SIMD12) || (varRegType == TYP_SIMD16));
38313832 regArgMaskLive &= ~genRegMask (regNum);
38323833 regArgTab[argNum].circular = false ;
38333834 change = true ;
@@ -4338,9 +4339,10 @@ void CodeGen::genFnPrologCalleeRegArgs(regNumber xtraReg, bool* pXtraRegClobbere
43384339
43394340 varNum = regArgTab[argNum].varNum ;
43404341 noway_assert (varNum < compiler->lvaCount );
4341- varDsc = compiler->lvaTable + varNum;
4342- var_types regType = regArgTab[argNum].getRegType (compiler);
4343- regNumber regNum = genMapRegArgNumToRegNum (argNum, regType);
4342+ varDsc = compiler->lvaTable + varNum;
4343+ const var_types regType = regArgTab[argNum].getRegType (compiler);
4344+ const regNumber regNum = genMapRegArgNumToRegNum (argNum, regType);
4345+ const var_types varRegType = varDsc->GetRegisterType ();
43444346
43454347#if defined(UNIX_AMD64_ABI)
43464348 if (regType == TYP_UNDEF)
@@ -4439,7 +4441,7 @@ void CodeGen::genFnPrologCalleeRegArgs(regNumber xtraReg, bool* pXtraRegClobbere
44394441 assert (regArgTab[argNum].slot == 2 );
44404442 assert (argNum > 0 );
44414443 assert (regArgTab[argNum - 1 ].slot == 1 );
4442- assert ((varDsc-> lvType == TYP_SIMD12) || (varDsc-> lvType == TYP_SIMD16));
4444+ assert ((varRegType == TYP_SIMD12) || (varRegType == TYP_SIMD16));
44434445 destRegNum = varDsc->GetRegNum ();
44444446 noway_assert (regNum != destRegNum);
44454447 continue ;
@@ -4509,7 +4511,7 @@ void CodeGen::genFnPrologCalleeRegArgs(regNumber xtraReg, bool* pXtraRegClobbere
45094511 noway_assert (regArgTab[nextArgNum].varNum == varNum);
45104512 // Emit a shufpd with a 0 immediate, which preserves the 0th element of the dest reg
45114513 // and moves the 0th element of the src reg into the 1st element of the dest reg.
4512- GetEmitter ()->emitIns_R_R_I (INS_shufpd, emitActualTypeSize (varDsc-> lvType ), destRegNum, nextRegNum, 0 );
4514+ GetEmitter ()->emitIns_R_R_I (INS_shufpd, emitActualTypeSize (varRegType ), destRegNum, nextRegNum, 0 );
45134515 // Set destRegNum to regNum so that we skip the setting of the register below,
45144516 // but mark argNum as processed and clear regNum from the live mask.
45154517 destRegNum = regNum;
@@ -11245,11 +11247,15 @@ void CodeGen::genStructReturn(GenTree* treeNode)
1124511247 assert (regCount <= MAX_RET_REG_COUNT);
1124611248
1124711249#if FEATURE_MULTIREG_RET
11250+ // Right now the only enregisterable structs supported are SIMD vector types.
1124811251 if (genIsRegCandidateLocal (actualOp1))
1124911252 {
11250- // Right now the only enregisterable structs supported are SIMD vector types.
11251- assert (varTypeIsSIMD (op1));
11252- assert (!actualOp1->AsLclVar ()->IsMultiReg ());
11253+ #if defined(DEBUG)
11254+ const GenTreeLclVar* lclVar = actualOp1->AsLclVar ();
11255+ const LclVarDsc* varDsc = compiler->lvaGetDesc (lclVar);
11256+ assert (varTypeIsSIMD (varDsc->GetRegisterType ()));
11257+ assert (!lclVar->IsMultiReg ());
11258+ #endif // DEBUG
1125311259#ifdef FEATURE_SIMD
1125411260 genSIMDSplitReturn (op1, &retTypeDesc);
1125511261#endif // FEATURE_SIMD
@@ -11329,6 +11335,7 @@ void CodeGen::genMultiRegStoreToLocal(GenTreeLclVar* lclNode)
1132911335 assert (op1->IsMultiRegNode ());
1133011336 unsigned regCount =
1133111337 actualOp1->IsMultiRegLclVar () ? actualOp1->AsLclVar ()->GetFieldCount (compiler) : actualOp1->GetMultiRegCount ();
11338+ assert (regCount > 1 );
1133211339
1133311340 // Assumption: current implementation requires that a multi-reg
1133411341 // var in 'var = call' is flagged as lvIsMultiRegRet to prevent it from
@@ -12580,3 +12587,61 @@ void CodeGen::genPoisonFrame(regMaskTP regLiveIn)
1258012587 }
1258112588 }
1258212589}
12590+
12591+ // ----------------------------------------------------------------------
12592+ // genBitCast - Generate the instruction to move a value between register files
12593+ //
12594+ // Arguments
12595+ // targetType - the destination type
12596+ // targetReg - the destination register
12597+ // srcType - the source type
12598+ // srcReg - the source register
12599+ //
12600+ void CodeGen::genBitCast (var_types targetType, regNumber targetReg, var_types srcType, regNumber srcReg)
12601+ {
12602+ const bool srcFltReg = varTypeUsesFloatReg (srcType) || varTypeIsSIMD (srcType);
12603+ assert (srcFltReg == genIsValidFloatReg (srcReg));
12604+
12605+ const bool dstFltReg = varTypeUsesFloatReg (targetType) || varTypeIsSIMD (targetType);
12606+ assert (dstFltReg == genIsValidFloatReg (targetReg));
12607+
12608+ inst_Mov (targetType, targetReg, srcReg, /* canSkip */ true );
12609+ }
12610+
12611+ // ----------------------------------------------------------------------
12612+ // genCodeForBitCast - Generate code for a GT_BITCAST that is not contained
12613+ //
12614+ // Arguments
12615+ // treeNode - the GT_BITCAST for which we're generating code
12616+ //
12617+ void CodeGen::genCodeForBitCast (GenTreeOp* treeNode)
12618+ {
12619+ regNumber targetReg = treeNode->GetRegNum ();
12620+ var_types targetType = treeNode->TypeGet ();
12621+ GenTree* op1 = treeNode->gtGetOp1 ();
12622+ genConsumeRegs (op1);
12623+
12624+ if (op1->isContained ())
12625+ {
12626+ assert (op1->IsLocal () || op1->isIndir ());
12627+ if (genIsRegCandidateLocal (op1))
12628+ {
12629+ unsigned lclNum = op1->AsLclVar ()->GetLclNum ();
12630+ GetEmitter ()->emitIns_R_S (ins_Load (treeNode->TypeGet (), compiler->isSIMDTypeLocalAligned (lclNum)),
12631+ emitTypeSize (treeNode), targetReg, lclNum, 0 );
12632+ }
12633+ else
12634+ {
12635+ op1->gtType = treeNode->TypeGet ();
12636+ op1->SetRegNum (targetReg);
12637+ op1->ClearContained ();
12638+ JITDUMP (" Changing type of BITCAST source to load directly.\n " );
12639+ genCodeForTreeNode (op1);
12640+ }
12641+ }
12642+ else
12643+ {
12644+ genBitCast (targetType, targetReg, op1->TypeGet (), op1->GetRegNum ());
12645+ }
12646+ genProduceReg (treeNode);
12647+ }
0 commit comments