Skip to content

Commit

Permalink
More TP tuning
Browse files Browse the repository at this point in the history
Another 0.025%.
  • Loading branch information
SingleAccretion committed Sep 25, 2022
1 parent f017e33 commit 7cd3df8
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 54 deletions.
17 changes: 9 additions & 8 deletions src/coreclr/jit/copyprop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ int Compiler::optCopyProp_LclVarScore(const LclVarDsc* lclVarDsc, const LclVarDs
// Arguments:
// stmt - Statement the tree belongs to
// tree - The local tree to perform copy propagation on
// lclNum - Number of the local "tree" refers to
// curSsaName - The map from lclNum to its recently live definitions as a stack
//
// Returns:
Expand Down Expand Up @@ -291,13 +292,6 @@ void Compiler::optCopyPropPushDef(GenTree* defNode, GenTreeLclVarCommon* lclNode
}

auto pushDef = [=](unsigned defLclNum, unsigned defSsaNum) {

// TODO-CQ: design better heuristics for propagation and remove this.
if ((defNode != nullptr) && defNode->IsPhiDefn())
{
defSsaNum = SsaConfig::RESERVED_SSA_NUM;
}

// The default is "not available".
LclSsaVarDsc* ssaDef = nullptr;

Expand Down Expand Up @@ -340,7 +334,14 @@ void Compiler::optCopyPropPushDef(GenTree* defNode, GenTreeLclVarCommon* lclNode
}
else if (lclNode->HasSsaName())
{
pushDef(lclNum, lclNode->GetSsaNum());
unsigned ssaNum = lclNode->GetSsaNum();
if ((defNode != nullptr) && defNode->IsPhiDefn())
{
// TODO-CQ: design better heuristics for propagation and remove this.
ssaNum = SsaConfig::RESERVED_SSA_NUM;
}

pushDef(lclNum, ssaNum);
}
}

Expand Down
5 changes: 2 additions & 3 deletions src/coreclr/jit/gentree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16406,9 +16406,8 @@ bool GenTree::IsPhiNode()

bool GenTree::IsPhiDefn()
{
bool res = ((OperGet() == GT_ASG) && (AsOp()->gtOp2 != nullptr) && (AsOp()->gtOp2->OperGet() == GT_PHI)) ||
((OperGet() == GT_STORE_LCL_VAR) && (AsOp()->gtOp1 != nullptr) && (AsOp()->gtOp1->OperGet() == GT_PHI));
assert(!res || OperGet() == GT_STORE_LCL_VAR || AsOp()->gtOp1->OperGet() == GT_LCL_VAR);
bool res = OperIs(GT_ASG) && AsOp()->gtOp2->OperIs(GT_PHI);
assert(!res || AsOp()->gtOp1->OperIs(GT_LCL_VAR));
return res;
}

Expand Down
93 changes: 51 additions & 42 deletions src/coreclr/jit/ssabuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -755,37 +755,9 @@ void SsaBuilder::RenameDef(GenTree* defNode, BasicBlock* block)
unsigned lclNum = lclNode->GetLclNum();
LclVarDsc* varDsc = m_pCompiler->lvaGetDesc(lclNum);

auto pushDef = [=](unsigned defLclNum, bool defIsFull) -> unsigned {
// Promoted variables are not in SSA, only their fields are.
assert(m_pCompiler->lvaInSsa(defLclNum) && !m_pCompiler->lvaGetDesc(defLclNum)->lvPromoted);

LclVarDsc* defVarDsc = m_pCompiler->lvaGetDesc(defLclNum);
unsigned defSsaNum = defVarDsc->lvPerSsaData.AllocSsaNum(
m_allocator, block, defNode->OperIs(GT_ASG) ? defNode->AsOp() : nullptr);

if (!defIsFull)
{
// This is a partial definition of a variable. The node records only the SSA number
// of the def. The SSA number of the old definition (the "use" portion) will be
// recorded in the SSA descriptor.
defVarDsc->GetPerSsaData(defSsaNum)->SetUseDefSsaNum(m_renameStack.Top(defLclNum));
}

m_renameStack.Push(block, defLclNum, defSsaNum);

// If necessary, add SSA name to the arg list of a phi def in any handlers for try
// blocks that "block" is within. (But only do this for "real" definitions, not phis.)
if (!defNode->IsPhiDefn())
{
AddDefToHandlerPhis(block, defLclNum, defSsaNum);
}

return defSsaNum;
};

if (m_pCompiler->lvaInSsa(lclNum))
{
lclNode->SetSsaNum(pushDef(lclNum, isFullDef));
lclNode->SetSsaNum(RenamePushDef(defNode, block, lclNum, isFullDef));
assert(!varDsc->IsAddressExposed()); // Cannot define SSA memory.
return;
}
Expand All @@ -800,24 +772,24 @@ void SsaBuilder::RenameDef(GenTree* defNode, BasicBlock* block)
{
ssize_t fieldStoreOffset;
unsigned fieldStoreSize;
unsigned defSsaNum = SsaConfig::RESERVED_SSA_NUM;
unsigned ssaNum = SsaConfig::RESERVED_SSA_NUM;

// Fast-path the common case of an "entire" store.
if (isFullDef)
{
defSsaNum = pushDef(fieldLclNum, /* defIsFull */ true);
ssaNum = RenamePushDef(defNode, block, fieldLclNum, /* defIsFull */ true);
}
else if (m_pCompiler->gtStoreDefinesField(
fieldVarDsc, offset, storeSize, &fieldStoreOffset, &fieldStoreSize))
else if (m_pCompiler->gtStoreDefinesField(fieldVarDsc, offset, storeSize, &fieldStoreOffset,
&fieldStoreSize))
{
defSsaNum = pushDef(fieldLclNum, ValueNumStore::LoadStoreIsEntire(genTypeSize(fieldVarDsc),
fieldStoreOffset,
fieldStoreSize));
ssaNum = RenamePushDef(defNode, block, fieldLclNum,
ValueNumStore::LoadStoreIsEntire(genTypeSize(fieldVarDsc),
fieldStoreOffset, fieldStoreSize));
}

if (defSsaNum != SsaConfig::RESERVED_SSA_NUM)
if (ssaNum != SsaConfig::RESERVED_SSA_NUM)
{
lclNode->SetSsaNum(m_pCompiler, index, defSsaNum);
lclNode->SetSsaNum(m_pCompiler, index, ssaNum);
}
}
}
Expand Down Expand Up @@ -885,6 +857,47 @@ void SsaBuilder::RenameDef(GenTree* defNode, BasicBlock* block)
}
}

//------------------------------------------------------------------------
// RenamePushDef: Create and push a new definition on the renaming stack.
//
// Arguments:
// defNode - The store node for the definition
// block - The block in which it occurs
// lclNum - Number of the local being defined
// isFullDef - Whether the def is "entire"
//
// Return Value:
// The pushed SSA number.
//
unsigned SsaBuilder::RenamePushDef(GenTree* defNode, BasicBlock* block, unsigned lclNum, bool isFullDef)
{
// Promoted variables are not in SSA, only their fields are.
assert(m_pCompiler->lvaInSsa(lclNum) && !m_pCompiler->lvaGetDesc(lclNum)->lvPromoted);

LclVarDsc* varDsc = m_pCompiler->lvaGetDesc(lclNum);
unsigned ssaNum =
varDsc->lvPerSsaData.AllocSsaNum(m_allocator, block, defNode->OperIs(GT_ASG) ? defNode->AsOp() : nullptr);

if (!isFullDef)
{
// This is a partial definition of a variable. The node records only the SSA number
// of the def. The SSA number of the old definition (the "use" portion) will be
// recorded in the SSA descriptor.
varDsc->GetPerSsaData(ssaNum)->SetUseDefSsaNum(m_renameStack.Top(lclNum));
}

m_renameStack.Push(block, lclNum, ssaNum);

// If necessary, add SSA name to the arg list of a phi def in any handlers for try
// blocks that "block" is within. (But only do this for "real" definitions, not phis.)
if (!defNode->IsPhiDefn())
{
AddDefToHandlerPhis(block, lclNum, ssaNum);
}

return ssaNum;
}

//------------------------------------------------------------------------
// RenameLclUse: Rename a use of a local variable.
//
Expand Down Expand Up @@ -1660,10 +1673,6 @@ bool SsaBuilder::IncludeInSsa(unsigned lclNum)
{
LclVarDsc* varDsc = m_pCompiler->lvaGetDesc(lclNum);

if (varDsc->IsAddressExposed())
{
return false; // We exclude address-exposed variables.
}
if (!varDsc->lvTracked)
{
return false; // SSA is only done for tracked variables
Expand Down
3 changes: 2 additions & 1 deletion src/coreclr/jit/ssabuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ class SsaBuilder
// Rename all definitions and uses within a block.
void BlockRenameVariables(BasicBlock* block);
// Rename a local or memory definition generated by a GT_ASG/GT_CALL node.
void RenameDef(GenTree* asgNode, BasicBlock* block);
void RenameDef(GenTree* defNode, BasicBlock* block);
unsigned RenamePushDef(GenTree* defNode, BasicBlock* block, unsigned lclNum, bool isFullDef);
// Rename a use of a local variable.
void RenameLclUse(GenTreeLclVarCommon* lclNode);

Expand Down

0 comments on commit 7cd3df8

Please sign in to comment.