[FuncSpec][NFC] Avoid redundant computations of DominatorTree/LoopInfo
authorMomchil Velikov <momchil.velikov@arm.com>
Fri, 28 Oct 2022 10:30:41 +0000 (11:30 +0100)
committerMomchil Velikov <momchil.velikov@arm.com>
Fri, 28 Oct 2022 15:08:41 +0000 (16:08 +0100)
The `FunctionSpecialization` pass needs loop analysis results for its
cost function. For this purpose, it computes the `DominatorTree` and
`LoopInfo` for a function in `getSpecializationBonus`.  This function,
however, is called O(number of call sites x number of arguments), but
the DominatorTree/LoopInfo can be computed just once.

This patch plugs into the PassManager infrastructure to obtain
LoopInfo for a function and removes ad-hoc computation from
`getSpecializatioBonus`.

Reviewed By: ChuanqiXu, labrinea

Differential Revision: https://reviews.llvm.org/D136332

llvm/include/llvm/Transforms/Utils/SCCPSolver.h
llvm/lib/Transforms/IPO/FunctionSpecialization.cpp
llvm/lib/Transforms/IPO/SCCP.cpp
llvm/lib/Transforms/Utils/SCCPSolver.cpp

index 17bd072..f37badb 100644 (file)
@@ -30,6 +30,7 @@ class Function;
 class GlobalVariable;
 class Instruction;
 class LLVMContext;
+class LoopInfo;
 class PostDominatorTree;
 class StructType;
 class TargetLibraryInfo;
@@ -41,6 +42,7 @@ struct AnalysisResultsForFn {
   std::unique_ptr<PredicateInfo> PredInfo;
   DominatorTree *DT;
   PostDominatorTree *PDT;
+  LoopInfo *LI;
 };
 
 /// Helper struct shared between Function Specialization and SCCP Solver.
@@ -77,6 +79,8 @@ public:
 
   const PredicateBase *getPredicateInfoFor(Instruction *I);
 
+  const LoopInfo &getLoopInfo(Function &F);
+
   DomTreeUpdater getDTU(Function &F);
 
   /// trackValueOfGlobalVariable - Clients can use this method to
index 4483d67..997e748 100644 (file)
@@ -463,7 +463,7 @@ private:
         }
 
         SpecializationInfo &S = Specializations.back().second;
-        S.Gain += getSpecializationBonus(A, C);
+        S.Gain += getSpecializationBonus(A, C, Solver.getLoopInfo(*F));
         S.Args.push_back({A, C});
       }
       Added = false;
@@ -580,7 +580,7 @@ private:
   }
 
   InstructionCost getUserBonus(User *U, llvm::TargetTransformInfo &TTI,
-                               LoopInfo &LI) {
+                               const LoopInfo &LI) {
     auto *I = dyn_cast_or_null<Instruction>(U);
     // If not an instruction we do not know how to evaluate.
     // Keep minimum possible cost for now so that it doesnt affect
@@ -605,10 +605,9 @@ private:
   }
 
   /// Compute a bonus for replacing argument \p A with constant \p C.
-  InstructionCost getSpecializationBonus(Argument *A, Constant *C) {
+  InstructionCost getSpecializationBonus(Argument *A, Constant *C,
+                                         const LoopInfo &LI) {
     Function *F = A->getParent();
-    DominatorTree DT(*F);
-    LoopInfo LI(DT);
     auto &TTI = (GetTTI)(*F);
     LLVM_DEBUG(dbgs() << "FnSpecialization: Analysing bonus for constant: "
                       << C->getNameOrAsOperand() << "\n");
index 0453af1..673bb23 100644 (file)
@@ -12,6 +12,7 @@
 
 #include "llvm/Transforms/IPO/SCCP.h"
 #include "llvm/Analysis/AssumptionCache.h"
+#include "llvm/Analysis/LoopInfo.h"
 #include "llvm/Analysis/PostDominators.h"
 #include "llvm/Analysis/TargetLibraryInfo.h"
 #include "llvm/Analysis/TargetTransformInfo.h"
@@ -32,7 +33,8 @@ PreservedAnalyses IPSCCPPass::run(Module &M, ModuleAnalysisManager &AM) {
     DominatorTree &DT = FAM.getResult<DominatorTreeAnalysis>(F);
     return {
         std::make_unique<PredicateInfo>(F, DT, FAM.getResult<AssumptionAnalysis>(F)),
-        &DT, FAM.getCachedResult<PostDominatorTreeAnalysis>(F)};
+        &DT, FAM.getCachedResult<PostDominatorTreeAnalysis>(F),
+        nullptr};
   };
 
   if (!runIPSCCP(M, DL, GetTLI, getAnalysis))
@@ -75,8 +77,9 @@ public:
               F, DT,
               this->getAnalysis<AssumptionCacheTracker>().getAssumptionCache(
                   F)),
-          nullptr,  // We cannot preserve the DT or PDT with the legacy pass
-          nullptr}; // manager, so set them to nullptr.
+          nullptr,  // We cannot preserve the LI, DT or PDT with the legacy pass
+          nullptr,  // manager, so set them to nullptr.
+          nullptr};
     };
 
     return runIPSCCP(M, DL, GetTLI, getAnalysis);
@@ -123,7 +126,8 @@ PreservedAnalyses FunctionSpecializationPass::run(Module &M,
     DominatorTree &DT = FAM.getResult<DominatorTreeAnalysis>(F);
     return {std::make_unique<PredicateInfo>(
                 F, DT, FAM.getResult<AssumptionAnalysis>(F)),
-            &DT, FAM.getCachedResult<PostDominatorTreeAnalysis>(F)};
+            &DT, FAM.getCachedResult<PostDominatorTreeAnalysis>(F),
+            &FAM.getResult<LoopAnalysis>(F)};
   };
 
   if (!runFunctionSpecialization(M, DL, GetTLI, GetTTI, GetAC, GetAnalysis))
@@ -171,8 +175,9 @@ struct FunctionSpecializationLegacyPass : public ModulePass {
               F, DT,
               this->getAnalysis<AssumptionCacheTracker>().getAssumptionCache(
                   F)),
-          nullptr,  // We cannot preserve the DT or PDT with the legacy pass
-          nullptr}; // manager, so set them to nullptr.
+          nullptr, // We cannot preserve the LI, DT, or PDT with the legacy pass
+          nullptr, // manager, so set them to nullptr.
+          nullptr};
     };
     return runFunctionSpecialization(M, DL, GetTLI, GetTTI, GetAC, GetAnalysis);
   }
index 044e46f..a345557 100644 (file)
@@ -339,6 +339,13 @@ public:
     return A->second.PredInfo->getPredicateInfoFor(I);
   }
 
+  const LoopInfo &getLoopInfo(Function &F) {
+    auto A = AnalysisResults.find(&F);
+    assert(A != AnalysisResults.end() && A->second.LI &&
+           "Need LoopInfo analysis results for function.");
+    return *A->second.LI;
+  }
+
   DomTreeUpdater getDTU(Function &F) {
     auto A = AnalysisResults.find(&F);
     assert(A != AnalysisResults.end() && "Need analysis results for function.");
@@ -1527,6 +1534,10 @@ const PredicateBase *SCCPSolver::getPredicateInfoFor(Instruction *I) {
   return Visitor->getPredicateInfoFor(I);
 }
 
+const LoopInfo &SCCPSolver::getLoopInfo(Function &F) {
+  return Visitor->getLoopInfo(F);
+}
+
 DomTreeUpdater SCCPSolver::getDTU(Function &F) { return Visitor->getDTU(F); }
 
 void SCCPSolver::trackValueOfGlobalVariable(GlobalVariable *GV) {