JIT: Pick some low-hanging fruit in physical promotion throughput (#86792)
authorJakob Botsch Nielsen <Jakob.botsch.nielsen@gmail.com>
Fri, 26 May 2023 19:39:48 +0000 (21:39 +0200)
committerGitHub <noreply@github.com>
Fri, 26 May 2023 19:39:48 +0000 (21:39 +0200)
* Skip any IR traversals entirely if there are no candidates locals for
  physical promotion
* During accounting, do a quick pre-check for candidates in each
  statement using the linked locals list, before doing the tree walk.

Result:
```
Collection                                       PDIFF
aspnet.run.windows.x64.checked.mch              -0.59%
benchmarks.run.windows.x64.checked.mch          -0.65%
benchmarks.run_pgo.windows.x64.checked.mch      -0.65%
benchmarks.run_tiered.windows.x64.checked.mch   -0.65%
coreclr_tests.run.windows.x64.checked.mch       -0.66%
libraries.crossgen2.windows.x64.checked.mch     -0.61%
libraries.pmi.windows.x64.checked.mch           -0.63%
libraries_tests.pmi.windows.x64.checked.mch     -0.68%
```

src/coreclr/jit/promotion.cpp
src/coreclr/jit/promotion.h

index 5aa4bb2..f2f32da 100644 (file)
@@ -573,7 +573,7 @@ public:
         {
             GenTreeLclVarCommon* lcl = tree->AsLclVarCommon();
             LclVarDsc*           dsc = m_compiler->lvaGetDesc(lcl);
-            if (!dsc->lvPromoted && (dsc->TypeGet() == TYP_STRUCT) && !dsc->IsAddressExposed())
+            if (Promotion::IsCandidateForPhysicalPromotion(dsc))
             {
                 var_types       accessType;
                 ClassLayout*    accessLayout;
@@ -1665,7 +1665,7 @@ bool ReplaceVisitor::MarkForReadBack(unsigned lcl, unsigned offs, unsigned size)
 //
 PhaseStatus Promotion::Run()
 {
-    if (m_compiler->lvaCount <= 0)
+    if (!HaveCandidateLocals())
     {
         return PhaseStatus::MODIFIED_NOTHING;
     }
@@ -1678,7 +1678,14 @@ PhaseStatus Promotion::Run()
 
         for (Statement* stmt : bb->Statements())
         {
-            localsUse.WalkTree(stmt->GetRootNodePointer(), nullptr);
+            for (GenTreeLclVarCommon* lcl : stmt->LocalsTreeList())
+            {
+                if (Promotion::IsCandidateForPhysicalPromotion(m_compiler->lvaGetDesc(lcl)))
+                {
+                    localsUse.WalkTree(stmt->GetRootNodePointer(), nullptr);
+                    break;
+                }
+            }
         }
     }
 
@@ -1818,6 +1825,38 @@ PhaseStatus Promotion::Run()
 }
 
 //------------------------------------------------------------------------
+// Promotion::HaveCandidateLocals:
+//   Check if there are any locals that are candidates for physical promotion.
+//
+// Returns:
+//   True if so.
+//
+bool Promotion::HaveCandidateLocals()
+{
+    for (unsigned lclNum = 0; lclNum < m_compiler->lvaCount; lclNum++)
+    {
+        if (IsCandidateForPhysicalPromotion(m_compiler->lvaGetDesc(lclNum)))
+        {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+//------------------------------------------------------------------------
+// Promotion::IsCandidateForPhysicalPromotion:
+//   Check if a specified local is a candidate for physical promotion.
+//
+// Returns:
+//   True if so.
+//
+bool Promotion::IsCandidateForPhysicalPromotion(LclVarDsc* dsc)
+{
+    return (dsc->TypeGet() == TYP_STRUCT) && !dsc->lvPromoted && !dsc->IsAddressExposed();
+}
+
+//------------------------------------------------------------------------
 // Promotion::InsertInitialReadBack:
 //   Insert IR to initially read a struct local's value into its promoted field locals.
 //
index 7f64613..24ebffe 100644 (file)
@@ -169,6 +169,10 @@ class Promotion
         return ~min;
     }
 
+    bool HaveCandidateLocals();
+
+    static bool IsCandidateForPhysicalPromotion(LclVarDsc* dsc);
+
 public:
     explicit Promotion(Compiler* compiler) : m_compiler(compiler)
     {