@@ -4911,9 +4911,8 @@ void CodeGen::genSIMDIntrinsicSetItem(GenTreeSIMD* simdNode)
4911
4911
// When a 16-byte SIMD value is live across a call, the register allocator will use this intrinsic
4912
4912
// to cause the upper half to be saved. It will first attempt to find another, unused, callee-save
4913
4913
// register. If such a register cannot be found, it will save it to an available caller-save register.
4914
- // In that case, this node will be marked GTF_SPILL, which will cause genProduceReg to save the 8 byte
4915
- // value to the stack. (Note that if there are no caller-save registers available, the entire 16 byte
4916
- // value will be spilled to the stack.)
4914
+ // In that case, this node will be marked GTF_SPILL, which will cause this method to save
4915
+ // the upper half to the lclVar's home location.
4917
4916
//
4918
4917
void CodeGen::genSIMDIntrinsicUpperSave (GenTreeSIMD* simdNode)
4919
4918
{
@@ -4928,7 +4927,23 @@ void CodeGen::genSIMDIntrinsicUpperSave(GenTreeSIMD* simdNode)
4928
4927
assert (targetReg != REG_NA);
4929
4928
getEmitter ()->emitIns_R_R_I_I (INS_mov, EA_8BYTE, targetReg, op1Reg, 0 , 1 );
4930
4929
4931
- genProduceReg (simdNode);
4930
+ if ((simdNode->gtFlags & GTF_SPILL) != 0 )
4931
+ {
4932
+ // This is not a normal spill; we'll spill it to the lclVar location.
4933
+ // The localVar must have a stack home.
4934
+ unsigned varNum = op1->AsLclVarCommon ()->gtLclNum ;
4935
+ LclVarDsc* varDsc = compiler->lvaGetDesc (varNum);
4936
+ assert (varDsc->lvOnFrame );
4937
+ // We want to store this to the upper 8 bytes of this localVar's home.
4938
+ int offset = 8 ;
4939
+
4940
+ emitAttr attr = emitTypeSize (TYP_SIMD8);
4941
+ getEmitter ()->emitIns_S_R (INS_str, attr, targetReg, varNum, offset);
4942
+ }
4943
+ else
4944
+ {
4945
+ genProduceReg (simdNode);
4946
+ }
4932
4947
}
4933
4948
4934
4949
// -----------------------------------------------------------------------------
@@ -4946,11 +4961,7 @@ void CodeGen::genSIMDIntrinsicUpperSave(GenTreeSIMD* simdNode)
4946
4961
// have their home register, this node has its targetReg on the lclVar child, and its source
4947
4962
// on the simdNode.
4948
4963
// Regarding spill, please see the note above on genSIMDIntrinsicUpperSave. If we have spilled
4949
- // an upper-half to a caller save register, this node will be marked GTF_SPILLED. However, unlike
4950
- // most spill scenarios, the saved tree will be different from the restored tree, but the spill
4951
- // restore logic, which is triggered by the call to genConsumeReg, requires us to provide the
4952
- // spilled tree (saveNode) in order to perform the reload. We can easily find that tree,
4953
- // as it is in the spill descriptor for the register from which it was saved.
4964
+ // an upper-half to the lclVar's home location, this node will be marked GTF_SPILLED.
4954
4965
//
4955
4966
void CodeGen::genSIMDIntrinsicUpperRestore (GenTreeSIMD* simdNode)
4956
4967
{
@@ -4966,9 +4977,14 @@ void CodeGen::genSIMDIntrinsicUpperRestore(GenTreeSIMD* simdNode)
4966
4977
assert (srcReg != REG_NA);
4967
4978
if (simdNode->gtFlags & GTF_SPILLED)
4968
4979
{
4969
- GenTree* saveNode = regSet.rsSpillDesc [srcReg]->spillTree ;
4970
- noway_assert (saveNode != nullptr && (saveNode->gtRegNum == srcReg));
4971
- genConsumeReg (saveNode);
4980
+ // The localVar must have a stack home.
4981
+ LclVarDsc* varDsc = compiler->lvaGetDesc (varNum);
4982
+ assert (varDsc->lvOnFrame );
4983
+ // We will load this from the upper 8 bytes of this localVar's home.
4984
+ int offset = 8 ;
4985
+
4986
+ emitAttr attr = emitTypeSize (TYP_SIMD8);
4987
+ getEmitter ()->emitIns_R_S (INS_ldr, attr, srcReg, varNum, offset);
4972
4988
}
4973
4989
getEmitter ()->emitIns_R_R_I_I (INS_mov, EA_8BYTE, lclVarReg, srcReg, 1 , 0 );
4974
4990
}
0 commit comments