Skip to content

Refactoring store liveness update #79723

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
3 changes: 1 addition & 2 deletions src/coreclr/jit/codegen.h
Original file line number Diff line number Diff line change
Expand Up @@ -1219,8 +1219,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

#endif // !defined(TARGET_64BIT)

// Do liveness update for register produced by the current node in codegen after
// code has been emitted for it.
void genUpdateLifeStore(GenTree* tree, regNumber targetReg, LclVarDsc* varDsc);
void genProduceReg(GenTree* tree);
void genSpillLocal(unsigned varNum, var_types type, GenTreeLclVar* lclNode, regNumber regNum);
void genUnspillLocal(
Expand Down
9 changes: 2 additions & 7 deletions src/coreclr/jit/codegenarm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1116,19 +1116,14 @@ void CodeGen::genCodeForStoreLclVar(GenTreeLclVar* tree)

emitter* emit = GetEmitter();
emit->emitIns_S_R(ins, attr, dataReg, varNum, /* offset */ 0);

// Updating variable liveness after instruction was emitted
genUpdateLife(tree);

varDsc->SetRegNum(REG_STK);
}
else // store into register (i.e move into register)
{
// Assign into targetReg when dataReg (from op1) is not the same register
inst_Mov(targetType, targetReg, dataReg, /* canSkip */ true);

genProduceReg(tree);
}

genUpdateLifeStore(tree, targetReg, varDsc);
}
}
}
Expand Down
21 changes: 10 additions & 11 deletions src/coreclr/jit/codegenarm64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2928,7 +2928,6 @@ void CodeGen::genCodeForStoreLclVar(GenTreeLclVar* lclNode)
if (targetReg != REG_NA)
{
emit->emitIns_R_I(INS_movi, emitActualTypeSize(targetType), targetReg, 0x00, INS_OPTS_16B);
genProduceReg(lclNode);
}
else
{
Expand All @@ -2941,8 +2940,8 @@ void CodeGen::genCodeForStoreLclVar(GenTreeLclVar* lclNode)
assert(targetType == TYP_SIMD8);
GetEmitter()->emitIns_S_R(INS_str, EA_8BYTE, REG_ZR, varNum, 0);
}
genUpdateLife(lclNode);
}
genUpdateLifeStore(lclNode, targetReg, varDsc);
return;
}
if (zeroInit)
Expand Down Expand Up @@ -2971,18 +2970,13 @@ void CodeGen::genCodeForStoreLclVar(GenTreeLclVar* lclNode)
emitAttr attr = emitActualTypeSize(targetType);

emit->emitIns_S_R(ins, attr, dataReg, varNum, /* offset */ 0);

genUpdateLife(lclNode);

varDsc->SetRegNum(REG_STK);
}
else // store into register (i.e move into register)
{
// Assign into targetReg when dataReg (from op1) is not the same register
inst_Mov(targetType, targetReg, dataReg, /* canSkip */ true);

genProduceReg(lclNode);
}
genUpdateLifeStore(lclNode, targetReg, varDsc);
}
}

Expand Down Expand Up @@ -5575,8 +5569,9 @@ void CodeGen::genStoreLclTypeSIMD12(GenTree* treeNode)

GenTreeLclVarCommon* lclVar = treeNode->AsLclVarCommon();

unsigned offs = lclVar->GetLclOffs();
unsigned varNum = lclVar->GetLclNum();
unsigned offs = lclVar->GetLclOffs();
unsigned varNum = lclVar->GetLclNum();
LclVarDsc* varDsc = compiler->lvaGetDesc(varNum);
assert(varNum < compiler->lvaCount);

GenTree* op1 = lclVar->gtGetOp1();
Expand All @@ -5592,6 +5587,10 @@ void CodeGen::genStoreLclTypeSIMD12(GenTree* treeNode)
// Store upper 4 bytes
GetEmitter()->emitIns_S_R(ins_Store(TYP_FLOAT), EA_4BYTE, REG_ZR, varNum, offs + 8);

// Update life after instruction emitted
genUpdateLife(treeNode);
varDsc->SetRegNum(REG_STK);

return;
}

Expand All @@ -5604,14 +5603,14 @@ void CodeGen::genStoreLclTypeSIMD12(GenTree* treeNode)

// Simply use mov if we move a SIMD12 reg to another SIMD12 reg
inst_Mov(treeNode->TypeGet(), targetReg, operandReg, /* canSkip */ true);
genProduceReg(treeNode);
}
else
{
// Need an additional integer register to extract upper 4 bytes from data.
regNumber tmpReg = lclVar->GetSingleTempReg();
GetEmitter()->emitStoreSIMD12ToLclOffset(varNum, offs, operandReg, tmpReg);
}
genUpdateLifeStore(treeNode, targetReg, varDsc);
}

#endif // FEATURE_SIMD
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/jit/codegencommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8769,6 +8769,7 @@ void CodeGenInterface::VariableLiveKeeper::VariableLiveDescriptor::endLiveRangeA
// Using [close, open) ranges so as to not compute the size of the last instruction
m_VariableLiveRanges->back().m_EndEmitLocation.CaptureLocation(emit);

JITDUMP("Closing debug range.\n");
// No m_EndEmitLocation has to be Valid
noway_assert(m_VariableLiveRanges->back().m_EndEmitLocation.Valid());
}
Expand Down
24 changes: 24 additions & 0 deletions src/coreclr/jit/codegenlinear.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2082,6 +2082,30 @@ void CodeGen::genSpillLocal(unsigned varNum, var_types type, GenTreeLclVar* lclN
}
}

//-------------------------------------------------------------------------
// genProduceReg: Do liveness udpate after tree store instructions were
// emitted, update result var's home if it was stored on stack.
//
// Arguments:
// tree - Gentree node
// targetReg - of the tree
// varDsc - result value's variable
//
// Return Value:
// None.
void CodeGen::genUpdateLifeStore(GenTree* tree, regNumber targetReg, LclVarDsc* varDsc)
{
if (targetReg != REG_NA)
{
genProduceReg(tree);
}
else
{
genUpdateLife(tree);
varDsc->SetRegNum(REG_STK);
}
}

//-------------------------------------------------------------------------
// genProduceReg: do liveness update for register produced by the current
// node in codegen after code has been emitted for it.
Expand Down
24 changes: 7 additions & 17 deletions src/coreclr/jit/codegenxarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4789,8 +4789,6 @@ void CodeGen::genCodeForStoreLclFld(GenTreeLclFld* tree)
assert(tree->OperIs(GT_STORE_LCL_FLD));

var_types targetType = tree->TypeGet();
GenTree* op1 = tree->gtGetOp1();

noway_assert(targetType != TYP_STRUCT);

#ifdef FEATURE_SIMD
Expand All @@ -4802,26 +4800,26 @@ void CodeGen::genCodeForStoreLclFld(GenTreeLclFld* tree)
}
#endif // FEATURE_SIMD

GenTree* op1 = tree->gtGetOp1();
regNumber targetReg = tree->GetRegNum();
unsigned lclNum = tree->GetLclNum();
LclVarDsc* varDsc = compiler->lvaGetDesc(lclNum);

assert(varTypeUsesFloatReg(targetType) == varTypeUsesFloatReg(op1));
assert(genTypeSize(genActualType(targetType)) == genTypeSize(genActualType(op1->TypeGet())));

genConsumeRegs(op1);

if (op1->OperIs(GT_BITCAST) && op1->isContained())
{
regNumber targetReg = tree->GetRegNum();
GenTree* bitCastSrc = op1->gtGetOp1();
var_types srcType = bitCastSrc->TypeGet();
noway_assert(!bitCastSrc->isContained());

if (targetReg == REG_NA)
{
unsigned lclNum = tree->GetLclNum();
LclVarDsc* varDsc = compiler->lvaGetDesc(lclNum);

GetEmitter()->emitIns_S_R(ins_Store(srcType, compiler->isSIMDTypeLocalAligned(lclNum)),
emitTypeSize(targetType), bitCastSrc->GetRegNum(), lclNum, tree->GetLclOffs());
varDsc->SetRegNum(REG_STK);
}
else
{
Expand All @@ -4832,9 +4830,7 @@ void CodeGen::genCodeForStoreLclFld(GenTreeLclFld* tree)
{
GetEmitter()->emitInsBinary(ins_Store(targetType), emitTypeSize(tree), tree, op1);
}

// Updating variable liveness after instruction was emitted
genUpdateLife(tree);
genUpdateLifeStore(tree, targetReg, varDsc);
}

//------------------------------------------------------------------------
Expand Down Expand Up @@ -4906,8 +4902,6 @@ void CodeGen::genCodeForStoreLclVar(GenTreeLclVar* lclNode)
{
emit->emitIns_S_R(ins_Store(srcType, compiler->isSIMDTypeLocalAligned(lclNum)),
emitTypeSize(targetType), bitCastSrc->GetRegNum(), lclNum, 0);
genUpdateLife(lclNode);
varDsc->SetRegNum(REG_STK);
}
else
{
Expand All @@ -4919,7 +4913,6 @@ void CodeGen::genCodeForStoreLclVar(GenTreeLclVar* lclNode)
// stack store
emit->emitInsStoreLcl(ins_Store(targetType, compiler->isSIMDTypeLocalAligned(lclNum)),
emitTypeSize(targetType), lclNode);
varDsc->SetRegNum(REG_STK);
}
else
{
Expand Down Expand Up @@ -4956,10 +4949,7 @@ void CodeGen::genCodeForStoreLclVar(GenTreeLclVar* lclNode)
emitTypeSize(targetType));
}
}
if (targetReg != REG_NA)
{
genProduceReg(lclNode);
}
genUpdateLifeStore(lclNode, targetReg, varDsc);
}
}

Expand Down
3 changes: 0 additions & 3 deletions src/coreclr/jit/emitxarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4492,9 +4492,6 @@ void emitter::emitInsStoreLcl(instruction ins, emitAttr attr, GenTreeLclVarCommo
assert(!data->isContained());
emitIns_S_R(ins, attr, data->GetRegNum(), varNode->GetLclNum(), 0);
}

// Updating variable liveness after instruction was emitted
codeGen->genUpdateLife(varNode);
}

//------------------------------------------------------------------------
Expand Down
38 changes: 25 additions & 13 deletions src/coreclr/jit/simdcodegenxarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -939,31 +939,43 @@ void CodeGen::genStoreLclTypeSIMD12(GenTree* treeNode)
assert((treeNode->OperGet() == GT_STORE_LCL_FLD) || (treeNode->OperGet() == GT_STORE_LCL_VAR));

const GenTreeLclVarCommon* lclVar = treeNode->AsLclVarCommon();

unsigned offs = lclVar->GetLclOffs();
unsigned varNum = lclVar->GetLclNum();
unsigned offs = lclVar->GetLclOffs();
unsigned varNum = lclVar->GetLclNum();
assert(varNum < compiler->lvaCount);

GenTree* op1 = lclVar->gtOp1;

assert(!op1->isContained());
regNumber operandReg = genConsumeReg(op1);
regNumber targetReg = treeNode->GetRegNum();
regNumber operandReg = genConsumeReg(op1);
LclVarDsc* varDsc = compiler->lvaGetDesc(varNum);

// store lower 8 bytes
GetEmitter()->emitIns_S_R(ins_Store(TYP_DOUBLE), EA_8BYTE, operandReg, varNum, offs);
if (targetReg != REG_NA)
{
assert(!GetEmitter()->isGeneralRegister(targetReg));

if (!op1->IsVectorZero())
inst_Mov(treeNode->TypeGet(), targetReg, operandReg, /* canSkip */ true);
}
else
{
regNumber tmpReg = treeNode->GetSingleTempReg();
// store lower 8 bytes
GetEmitter()->emitIns_S_R(ins_Store(TYP_DOUBLE), EA_8BYTE, operandReg, varNum, offs);

if (!op1->IsVectorZero())
{
regNumber tmpReg = treeNode->GetSingleTempReg();

// Extract upper 4-bytes from operandReg
GetEmitter()->emitIns_R_R_I(INS_pshufd, emitActualTypeSize(TYP_SIMD16), tmpReg, operandReg, 0x02);
// Extract upper 4-bytes from operandReg
GetEmitter()->emitIns_R_R_I(INS_pshufd, emitActualTypeSize(TYP_SIMD16), tmpReg, operandReg, 0x02);

operandReg = tmpReg;
}

operandReg = tmpReg;
// Store upper 4 bytes
GetEmitter()->emitIns_S_R(ins_Store(TYP_FLOAT), EA_4BYTE, operandReg, varNum, offs + 8);
}

// Store upper 4 bytes
GetEmitter()->emitIns_S_R(ins_Store(TYP_FLOAT), EA_4BYTE, operandReg, varNum, offs + 8);
genUpdateLifeStore(treeNode, targetReg, varDsc);
}

//-----------------------------------------------------------------------------
Expand Down