Skip to content
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

JIT: Do not propagate some constants #70378

Merged
merged 11 commits into from
Jun 10, 2022
Merged
58 changes: 58 additions & 0 deletions src/coreclr/jit/assertionprop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3177,6 +3177,15 @@ GenTree* Compiler::optVNConstantPropOnTree(BasicBlock* block, GenTree* tree)

if (conValTree != nullptr)
{
if (tree->OperIs(GT_LCL_VAR))
{
if (!optIsProfitableToSubstitute(tree->AsLclVar(), block, conValTree))
{
// Not profitable to substitute
return nullptr;
}
}

// Were able to optimize.
conValTree->gtVNPair = vnPair;
GenTree* sideEffList = optExtractSideEffListFromConst(tree);
Expand All @@ -3199,6 +3208,55 @@ GenTree* Compiler::optVNConstantPropOnTree(BasicBlock* block, GenTree* tree)
}
}

//------------------------------------------------------------------------------
// optIsProfitableToSubstitute: Checks if value worth substituting to lcl location
//
// Arguments:
// lcl - lcl to replace with value if profitable
// lclBlock - Basic block lcl located in
// value - value we plan to substitute to lcl
//
// Returns:
// False if it's likely not profitable to do substitution, True otherwise
//
bool Compiler::optIsProfitableToSubstitute(GenTreeLclVarCommon* lcl, BasicBlock* lclBlock, GenTree* value)
{
// A simple heuristic: If the constant is defined outside of a loop (not far from its head)
// and is used inside it - don't propagate.

// TODO: Extend on more kinds of trees
if (!value->OperIs(GT_CNS_VEC, GT_CNS_DBL))
{
return true;
}

gtPrepareCost(value);

if ((value->GetCostEx() > 1) && (value->GetCostSz() > 1))
{
// Try to find the block this constant was originally defined in
if (lcl->HasSsaName())
{
BasicBlock* defBlock = lvaGetDesc(lcl)->GetPerSsaData(lcl->GetSsaNum())->GetBlock();
if (defBlock != nullptr)
{
// Avoid propagating if the weighted use cost is significantly greater than the def cost.
// NOTE: this currently does not take "a float living across a call" case into account
// where we might end up with spill/restore on ABIs without callee-saved registers
const weight_t defBlockWeight = defBlock->getBBWeight(this);
const weight_t lclblockWeight = lclBlock->getBBWeight(this);

if ((defBlockWeight > 0) && ((lclblockWeight / defBlockWeight) >= BB_LOOP_WEIGHT_SCALE))
{
JITDUMP("Constant propagation inside loop " FMT_BB " is not profitable\n", lclBlock->bbNum);
return false;
}
}
}
}
return true;
}

//------------------------------------------------------------------------------
// optConstantAssertionProp: Possibly substitute a constant for a local use
//
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -7264,6 +7264,7 @@ class Compiler
GenTree* optConstantAssertionProp(AssertionDsc* curAssertion,
GenTreeLclVarCommon* tree,
Statement* stmt DEBUGARG(AssertionIndex index));
bool optIsProfitableToSubstitute(GenTreeLclVarCommon* lcl, BasicBlock* lclBlock, GenTree* value);
bool optZeroObjAssertionProp(GenTree* tree, ASSERT_VALARG_TP assertions);

// Assertion propagation functions.
Expand Down