diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index 9a4be3c6e4e9e3..116edfa0a96574 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -3280,21 +3280,55 @@ bool Compiler::optIsProfitableToSubstitute(GenTreeLclVarCommon* lcl, BasicBlock* // 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); + auto isBlockWeightDifferenceTooBig = [](Compiler* comp, BasicBlock* defBlock, BasicBlock* useBlock) -> bool { + 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(comp); + const weight_t lclblockWeight = useBlock->getBBWeight(comp); - if ((defBlockWeight > 0) && ((lclblockWeight / defBlockWeight) >= BB_LOOP_WEIGHT_SCALE)) + if ((defBlockWeight > 0) && ((lclblockWeight / defBlockWeight) >= 4)) + { + return true; + } + } + return false; + }; + + // Scan up to 4 defs to see if we have a def with much lower block's weight + GenTreeLclVarCommon* currlcl = lcl; + for (size_t i = 0; i < 4; i++) + { + if (currlcl->GetSsaNum() == SsaConfig::RESERVED_SSA_NUM) + { + return true; + } + LclSsaVarDsc* def = lvaGetDesc(currlcl)->GetPerSsaData(currlcl->GetSsaNum()); + if (def == nullptr) + { + return true; + } + if (isBlockWeightDifferenceTooBig(this, def->GetBlock(), lclBlock)) { - JITDUMP("Constant propagation inside loop " FMT_BB " is not profitable\n", lclBlock->bbNum); return false; } + GenTreeOp* asgNode = def->GetAssignment(); + if (asgNode != nullptr) + { + GenTree* lhs = asgNode->gtGetOp1(); + GenTree* rhs = asgNode->gtGetOp2(); + if (rhs->IsLocal() && lhs->IsLocal() && lhs->AsLclVarCommon()->GetLclNum() == currlcl->GetLclNum()) + { + currlcl = rhs->AsLclVarCommon(); + continue; + } + } + + return true; } + } } return true; diff --git a/src/coreclr/scripts/superpmi_diffs.py b/src/coreclr/scripts/superpmi_diffs.py index aaedd05155377c..16aa288dc6872b 100644 --- a/src/coreclr/scripts/superpmi_diffs.py +++ b/src/coreclr/scripts/superpmi_diffs.py @@ -207,6 +207,7 @@ def main(main_args): os.path.join(script_dir, "superpmi.py"), "asmdiffs", "--no_progress", + "-metrics", "PerfScore", "-core_root", core_root_dir, "-target_os", platform_name, "-target_arch", arch_name,