[llvm] [Analysis] Avoid running transform passes that have just been run (PR #112092)

Yingwei Zheng via llvm-commits llvm-commits at lists.llvm.org
Mon Oct 14 03:22:50 PDT 2024


https://github.com/dtcxzyw updated https://github.com/llvm/llvm-project/pull/112092

>From 84cdd4b6fe5a4639371bb9e8255f3f0048b10638 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Sat, 12 Oct 2024 10:14:24 +0800
Subject: [PATCH 1/7] [Analysis] Avoid running transform passes that have just
 been run

---
 .../llvm/Analysis/LastRunTrackingAnalysis.h   | 91 +++++++++++++++++++
 .../llvm/Transforms/InstCombine/InstCombine.h |  7 ++
 llvm/lib/Analysis/CMakeLists.txt              |  1 +
 llvm/lib/Analysis/LastRunTrackingAnalysis.cpp | 41 +++++++++
 llvm/lib/Passes/PassBuilder.cpp               |  1 +
 llvm/lib/Passes/PassRegistry.def              |  2 +
 .../InstCombine/InstructionCombining.cpp      | 14 ++-
 7 files changed, 156 insertions(+), 1 deletion(-)
 create mode 100644 llvm/include/llvm/Analysis/LastRunTrackingAnalysis.h
 create mode 100644 llvm/lib/Analysis/LastRunTrackingAnalysis.cpp

diff --git a/llvm/include/llvm/Analysis/LastRunTrackingAnalysis.h b/llvm/include/llvm/Analysis/LastRunTrackingAnalysis.h
new file mode 100644
index 00000000000000..39a7f618310aa5
--- /dev/null
+++ b/llvm/include/llvm/Analysis/LastRunTrackingAnalysis.h
@@ -0,0 +1,91 @@
+//===- LastRunTrackingAnalysis.h - Avoid running redundant pass -*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This is an analysis pass to track a set of passes that have been run, so that
+// we can avoid running a pass again if there is no change since the last run of
+// the pass.
+//
+// In this pass we track a set of passes S for each function with the following
+// transition rules:
+//   1. If pass P make changes, set S = {P}.
+//   2. If pass P doesn't make changes, set S = S + {P}.
+//
+// Before running a pass P which satisfies P(P(x)) == P(x), we check if P is in
+// S. If so, we skip this pass since we know that there will be no change.
+//
+// Notes:
+//   1. Some transform passes have parameters that may vary in the optimization
+//   pipeline. We should check if parameters in current run is compatible with
+//   that in the last run.
+//   2. Module passes are specially handled. If a module pass make changes, we
+//   clear all sets.
+//   3. This pass only tracks at the function level. Loop passes are not
+//   supported for now.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ANALYSIS_LASTRUNTRACKINGANALYSIS_H
+#define LLVM_ANALYSIS_LASTRUNTRACKINGANALYSIS_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/IR/PassManager.h"
+#include <functional>
+
+namespace llvm {
+
+/// TODO: class desc/PassID/OptionT::isCompatibleWith
+class LastRunTrackingInfo {
+public:
+  using PassID = const void *;
+  using OptionPtr = const void *;
+  // CompatibilityCheckFn is a closure that stores the parameters of last run.
+  using CompatibilityCheckFn = std::function<bool(OptionPtr)>;
+
+  /// TODO:
+  template <typename OptionT>
+  bool shouldSkip(PassID ID, const OptionT &Opt) const {
+    return shouldSkipImpl(ID, &Opt);
+  }
+  bool shouldSkip(PassID ID) const { return shouldSkipImpl(ID, nullptr); }
+
+  /// TODO:
+  template <typename OptionT>
+  void update(PassID ID, bool Changed, const OptionT &Opt) {
+    updateImpl(ID, Changed, [Opt](OptionPtr Ptr) {
+      return static_cast<const OptionT *>(Ptr)->isCompatibleWith(Opt);
+    });
+  }
+  void update(PassID ID, bool Changed) {
+    updateImpl(ID, Changed, CompatibilityCheckFn{});
+  }
+
+private:
+  bool shouldSkipImpl(PassID ID, OptionPtr Ptr) const;
+  void updateImpl(PassID ID, bool Changed, CompatibilityCheckFn CheckFn);
+
+  DenseMap<PassID, CompatibilityCheckFn> TrackedPasses;
+};
+
+class LastRunTrackingAnalysis final
+    : public AnalysisInfoMixin<LastRunTrackingAnalysis> {
+  friend AnalysisInfoMixin<LastRunTrackingAnalysis>;
+  static AnalysisKey Key;
+
+public:
+  using Result = LastRunTrackingInfo;
+  LastRunTrackingInfo run(Function &F, FunctionAnalysisManager &) {
+    return LastRunTrackingInfo();
+  }
+  LastRunTrackingInfo run(Module &M, ModuleAnalysisManager &) {
+    return LastRunTrackingInfo();
+  }
+};
+
+} // namespace llvm
+
+#endif // LLVM_ANALYSIS_LASTRUNTRACKINGANALYSIS_H
diff --git a/llvm/include/llvm/Transforms/InstCombine/InstCombine.h b/llvm/include/llvm/Transforms/InstCombine/InstCombine.h
index b4f0166239520a..21307b978734b0 100644
--- a/llvm/include/llvm/Transforms/InstCombine/InstCombine.h
+++ b/llvm/include/llvm/Transforms/InstCombine/InstCombine.h
@@ -43,12 +43,19 @@ struct InstCombineOptions {
     MaxIterations = Value;
     return *this;
   }
+
+  /// Only enable skipping in standard optimization pipeline.
+  bool isCompatibleWith(const InstCombineOptions &LastOption) const {
+    return !VerifyFixpoint && !LastOption.VerifyFixpoint &&
+           MaxIterations == 1 && LastOption.MaxIterations == 1;
+  }
 };
 
 class InstCombinePass : public PassInfoMixin<InstCombinePass> {
 private:
   InstructionWorklist Worklist;
   InstCombineOptions Options;
+  static char ID;
 
 public:
   explicit InstCombinePass(InstCombineOptions Opts = {});
diff --git a/llvm/lib/Analysis/CMakeLists.txt b/llvm/lib/Analysis/CMakeLists.txt
index 393803fad89383..0db5b80f336cb5 100644
--- a/llvm/lib/Analysis/CMakeLists.txt
+++ b/llvm/lib/Analysis/CMakeLists.txt
@@ -79,6 +79,7 @@ add_llvm_component_library(LLVMAnalysis
   InstructionPrecedenceTracking.cpp
   InstructionSimplify.cpp
   InteractiveModelRunner.cpp
+  LastRunTrackingAnalysis.cpp
   LazyBranchProbabilityInfo.cpp
   LazyBlockFrequencyInfo.cpp
   LazyCallGraph.cpp
diff --git a/llvm/lib/Analysis/LastRunTrackingAnalysis.cpp b/llvm/lib/Analysis/LastRunTrackingAnalysis.cpp
new file mode 100644
index 00000000000000..598a6cec9a06d0
--- /dev/null
+++ b/llvm/lib/Analysis/LastRunTrackingAnalysis.cpp
@@ -0,0 +1,41 @@
+//===- LastRunTrackingAnalysis.cpp - Avoid running redundant pass -*- C++ -*-=//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This is an analysis pass to track a set of passes that have been run, so that
+// we can avoid running a pass again if there is no change since the last run of
+// the pass.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Analysis/LastRunTrackingAnalysis.h"
+#include "llvm/Support/CommandLine.h"
+
+using namespace llvm;
+
+static cl::opt<bool>
+    DisableLastRunTracking("disable-last-run-tracking", cl::Hidden,
+                           cl::desc("Disable last run tracking"),
+                           cl::init(false));
+
+bool LastRunTrackingInfo::shouldSkipImpl(PassID ID, OptionPtr Ptr) const {
+  if (DisableLastRunTracking)
+    return false;
+  auto Iter = TrackedPasses.find(ID);
+  if (Iter == TrackedPasses.end())
+    return false;
+  return !Iter->second || Iter->second(Ptr);
+}
+
+void LastRunTrackingInfo::updateImpl(PassID ID, bool Changed,
+                                     CompatibilityCheckFn CheckFn) {
+  if (Changed)
+    TrackedPasses.clear();
+  TrackedPasses[ID] = std::move(CheckFn);
+}
+
+AnalysisKey LastRunTrackingAnalysis::Key;
diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp
index f47f8ca35d7737..e515a86d1bf310 100644
--- a/llvm/lib/Passes/PassBuilder.cpp
+++ b/llvm/lib/Passes/PassBuilder.cpp
@@ -46,6 +46,7 @@
 #include "llvm/Analysis/InlineAdvisor.h"
 #include "llvm/Analysis/InlineSizeEstimatorAnalysis.h"
 #include "llvm/Analysis/InstCount.h"
+#include "llvm/Analysis/LastRunTrackingAnalysis.h"
 #include "llvm/Analysis/LazyCallGraph.h"
 #include "llvm/Analysis/LazyValueInfo.h"
 #include "llvm/Analysis/Lint.h"
diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def
index 90859c18c4f499..55fb8135ddd41c 100644
--- a/llvm/lib/Passes/PassRegistry.def
+++ b/llvm/lib/Passes/PassRegistry.def
@@ -25,6 +25,7 @@ MODULE_ANALYSIS("dxil-metadata", DXILMetadataAnalysis())
 MODULE_ANALYSIS("dxil-resource", DXILResourceAnalysis())
 MODULE_ANALYSIS("inline-advisor", InlineAdvisorAnalysis())
 MODULE_ANALYSIS("ir-similarity", IRSimilarityAnalysis())
+MODULE_ANALYSIS("last-run-tracking", LastRunTrackingAnalysis())
 MODULE_ANALYSIS("lcg", LazyCallGraphAnalysis())
 MODULE_ANALYSIS("module-summary", ModuleSummaryIndexAnalysis())
 MODULE_ANALYSIS("no-op-module", NoOpModuleAnalysis())
@@ -285,6 +286,7 @@ FUNCTION_ANALYSIS(
     MachineFunctionAnalysis(static_cast<const LLVMTargetMachine *>(TM)))
 FUNCTION_ANALYSIS("gc-function", GCFunctionAnalysis())
 FUNCTION_ANALYSIS("inliner-size-estimator", InlineSizeEstimatorAnalysis())
+FUNCTION_ANALYSIS("last-run-tracking", LastRunTrackingAnalysis())
 FUNCTION_ANALYSIS("lazy-value-info", LazyValueAnalysis())
 FUNCTION_ANALYSIS("loops", LoopAnalysis())
 FUNCTION_ANALYSIS("memdep", MemoryDependenceAnalysis())
diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index 954c4cf19c2077..1a512cae7bf778 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -47,6 +47,7 @@
 #include "llvm/Analysis/ConstantFolding.h"
 #include "llvm/Analysis/GlobalsModRef.h"
 #include "llvm/Analysis/InstructionSimplify.h"
+#include "llvm/Analysis/LastRunTrackingAnalysis.h"
 #include "llvm/Analysis/LazyBlockFrequencyInfo.h"
 #include "llvm/Analysis/MemoryBuiltins.h"
 #include "llvm/Analysis/OptimizationRemarkEmitter.h"
@@ -5538,8 +5539,15 @@ void InstCombinePass::printPipeline(
   OS << '>';
 }
 
+char InstCombinePass::ID = 0;
+
 PreservedAnalyses InstCombinePass::run(Function &F,
                                        FunctionAnalysisManager &AM) {
+  auto &LRT = AM.getResult<LastRunTrackingAnalysis>(F);
+  // No changes since last InstCombine pass, exit early.
+  if (LRT.shouldSkip(&ID, Options))
+    return PreservedAnalyses::all();
+
   auto &AC = AM.getResult<AssumptionAnalysis>(F);
   auto &DT = AM.getResult<DominatorTreeAnalysis>(F);
   auto &TLI = AM.getResult<TargetLibraryAnalysis>(F);
@@ -5555,12 +5563,16 @@ PreservedAnalyses InstCombinePass::run(Function &F,
   auto *BPI = AM.getCachedResult<BranchProbabilityAnalysis>(F);
 
   if (!combineInstructionsOverFunction(F, Worklist, AA, AC, TLI, TTI, DT, ORE,
-                                       BFI, BPI, PSI, Options))
+                                       BFI, BPI, PSI, Options)) {
     // No changes, all analyses are preserved.
+    LRT.update(&ID, /*Changed=*/false, Options);
     return PreservedAnalyses::all();
+  }
 
   // Mark all the analyses that instcombine updates as preserved.
   PreservedAnalyses PA;
+  LRT.update(&ID, /*Changed=*/true, Options);
+  PA.preserve<LastRunTrackingAnalysis>();
   PA.preserveSet<CFGAnalyses>();
   return PA;
 }

>From 1b9fab881127c93c882e7272198ca4c67ee9c668 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Sun, 13 Oct 2024 11:06:47 +0800
Subject: [PATCH 2/7] [Analysis] Add comments

---
 .../llvm/Analysis/LastRunTrackingAnalysis.h   | 24 ++++++++++++++++---
 1 file changed, 21 insertions(+), 3 deletions(-)

diff --git a/llvm/include/llvm/Analysis/LastRunTrackingAnalysis.h b/llvm/include/llvm/Analysis/LastRunTrackingAnalysis.h
index 39a7f618310aa5..bd2520b22db903 100644
--- a/llvm/include/llvm/Analysis/LastRunTrackingAnalysis.h
+++ b/llvm/include/llvm/Analysis/LastRunTrackingAnalysis.h
@@ -38,7 +38,13 @@
 
 namespace llvm {
 
-/// TODO: class desc/PassID/OptionT::isCompatibleWith
+/// This class is used to track the last run of a set of module/function passes.
+/// Invalidation are conservatively handled by the pass manager if a pass
+/// doesn't explicitly preserve the result.
+/// If we want to skip a pass, we should define a unique ID \p PassID to
+/// identify the pass, which is usually a pointer to a static member. If a pass
+/// has parameters, they should be stored in a struct \p OptionT with a method
+/// bool isCompatibleWith(const OptionT& LastOpt) const to check compatibility.
 class LastRunTrackingInfo {
 public:
   using PassID = const void *;
@@ -46,14 +52,25 @@ class LastRunTrackingInfo {
   // CompatibilityCheckFn is a closure that stores the parameters of last run.
   using CompatibilityCheckFn = std::function<bool(OptionPtr)>;
 
-  /// TODO:
+  /// Check if we should skip a pass.
+  /// \param ID The unique ID of the pass.
+  /// \param Opt The parameters of the pass. If the pass has no parameters, use
+  /// shouldSkip(PassID ID) instead.
+  /// \return True if we should skip the pass.
+  /// \sa shouldSkip(PassID ID)
   template <typename OptionT>
   bool shouldSkip(PassID ID, const OptionT &Opt) const {
     return shouldSkipImpl(ID, &Opt);
   }
   bool shouldSkip(PassID ID) const { return shouldSkipImpl(ID, nullptr); }
 
-  /// TODO:
+  /// Update the tracking info.
+  /// \param ID The unique ID of the pass.
+  /// \param Changed Whether the pass makes changes.
+  /// \param Opt The parameters of the pass. It must have the same type as the
+  /// parameters of the last run. If the pass has no parameters, use
+  /// update(PassID ID, bool Changed) instead.
+  /// \sa update(PassID ID, bool Changed)
   template <typename OptionT>
   void update(PassID ID, bool Changed, const OptionT &Opt) {
     updateImpl(ID, Changed, [Opt](OptionPtr Ptr) {
@@ -71,6 +88,7 @@ class LastRunTrackingInfo {
   DenseMap<PassID, CompatibilityCheckFn> TrackedPasses;
 };
 
+/// A function/module analysis which provides an empty \c LastRunTrackingInfo.
 class LastRunTrackingAnalysis final
     : public AnalysisInfoMixin<LastRunTrackingAnalysis> {
   friend AnalysisInfoMixin<LastRunTrackingAnalysis>;

>From 2b3ef5c87e5d8d94f09aef18834aa90b5aaaa44f Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Sun, 13 Oct 2024 11:09:34 +0800
Subject: [PATCH 3/7] [InstCombine] Adjust `isCompatibleWith`

---
 llvm/include/llvm/Transforms/InstCombine/InstCombine.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/llvm/include/llvm/Transforms/InstCombine/InstCombine.h b/llvm/include/llvm/Transforms/InstCombine/InstCombine.h
index 21307b978734b0..5203f4cfeb976b 100644
--- a/llvm/include/llvm/Transforms/InstCombine/InstCombine.h
+++ b/llvm/include/llvm/Transforms/InstCombine/InstCombine.h
@@ -47,7 +47,8 @@ struct InstCombineOptions {
   /// Only enable skipping in standard optimization pipeline.
   bool isCompatibleWith(const InstCombineOptions &LastOption) const {
     return !VerifyFixpoint && !LastOption.VerifyFixpoint &&
-           MaxIterations == 1 && LastOption.MaxIterations == 1;
+           MaxIterations == InstCombineDefaultMaxIterations &&
+           LastOption.MaxIterations == InstCombineDefaultMaxIterations;
   }
 };
 

>From a05d9b574cf7a06d4a27c6e27ea4364817f7eff1 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Sun, 13 Oct 2024 11:44:28 +0800
Subject: [PATCH 4/7] [Analysis][NFC] Fix tests

---
 llvm/test/Other/new-pm-defaults.ll                        | 1 +
 llvm/test/Other/new-pm-lto-defaults.ll                    | 1 +
 llvm/test/Other/new-pm-thinlto-postlink-defaults.ll       | 1 +
 llvm/test/Other/new-pm-thinlto-postlink-pgo-defaults.ll   | 1 +
 .../Other/new-pm-thinlto-postlink-samplepgo-defaults.ll   | 1 +
 llvm/test/Other/new-pm-thinlto-prelink-defaults.ll        | 1 +
 llvm/test/Other/new-pm-thinlto-prelink-pgo-defaults.ll    | 2 ++
 .../Other/new-pm-thinlto-prelink-samplepgo-defaults.ll    | 1 +
 llvm/test/Transforms/Coroutines/coro-retcon-opaque-ptr.ll | 8 +++++---
 llvm/test/Transforms/Coroutines/coro-retcon.ll            | 6 ++++--
 llvm/unittests/Target/X86/TernlogTest.cpp                 | 1 +
 11 files changed, 19 insertions(+), 5 deletions(-)

diff --git a/llvm/test/Other/new-pm-defaults.ll b/llvm/test/Other/new-pm-defaults.ll
index 55dbdb1b8366d6..7cf035b0c6f376 100644
--- a/llvm/test/Other/new-pm-defaults.ll
+++ b/llvm/test/Other/new-pm-defaults.ll
@@ -118,6 +118,7 @@
 ; CHECK-O-NEXT: Running pass: GlobalOptPass
 ; CHECK-O-NEXT: Running pass: PromotePass
 ; CHECK-O-NEXT: Running pass: InstCombinePass
+; CHECK-O-NEXT: Running analysis: LastRunTrackingAnalysis
 ; CHECK-O-NEXT: Running analysis: OptimizationRemarkEmitterAnalysis
 ; CHECK-O-NEXT: Running analysis: AAManager
 ; CHECK-O-NEXT: Running analysis: BasicAA
diff --git a/llvm/test/Other/new-pm-lto-defaults.ll b/llvm/test/Other/new-pm-lto-defaults.ll
index 5543472df685b0..3d2d80da96785d 100644
--- a/llvm/test/Other/new-pm-lto-defaults.ll
+++ b/llvm/test/Other/new-pm-lto-defaults.ll
@@ -67,6 +67,7 @@
 ; CHECK-O23SZ-NEXT: Running pass: ConstantMergePass
 ; CHECK-O23SZ-NEXT: Running pass: DeadArgumentEliminationPass
 ; CHECK-O23SZ-NEXT: Running pass: InstCombinePass
+; CHECK-O23SZ-NEXT: Running analysis: LastRunTrackingAnalysis
 ; CHECK-O23SZ-NEXT: Running pass: AggressiveInstCombinePass
 ; CHECK-EP-Peephole-NEXT: Running pass: NoOpFunctionPass
 ; CHECK-O23SZ-NEXT: Running pass: ExpandVariadicsPass
diff --git a/llvm/test/Other/new-pm-thinlto-postlink-defaults.ll b/llvm/test/Other/new-pm-thinlto-postlink-defaults.ll
index fcf84dc5e11051..ed13402e1c4b15 100644
--- a/llvm/test/Other/new-pm-thinlto-postlink-defaults.ll
+++ b/llvm/test/Other/new-pm-thinlto-postlink-defaults.ll
@@ -54,6 +54,7 @@
 ; CHECK-O-NEXT: Running analysis: TargetLibraryAnalysis
 ; CHECK-O-NEXT: Running pass: PromotePass
 ; CHECK-O-NEXT: Running pass: InstCombinePass
+; CHECK-O-NEXT: Running analysis: LastRunTrackingAnalysis
 ; CHECK-O-NEXT: Running analysis: TargetLibraryAnalysis
 ; CHECK-O-NEXT: Running analysis: AAManager
 ; CHECK-O-NEXT: Running analysis: BasicAA
diff --git a/llvm/test/Other/new-pm-thinlto-postlink-pgo-defaults.ll b/llvm/test/Other/new-pm-thinlto-postlink-pgo-defaults.ll
index 4d5b5e733a87c2..c82c34f7ff01e7 100644
--- a/llvm/test/Other/new-pm-thinlto-postlink-pgo-defaults.ll
+++ b/llvm/test/Other/new-pm-thinlto-postlink-pgo-defaults.ll
@@ -39,6 +39,7 @@
 ; CHECK-O-NEXT: Running analysis: TargetLibraryAnalysis
 ; CHECK-O-NEXT: Running pass: PromotePass
 ; CHECK-O-NEXT: Running pass: InstCombinePass
+; CHECK-O-NEXT: Running analysis: LastRunTrackingAnalysis
 ; CHECK-O-NEXT: Running analysis: TargetLibraryAnalysis
 ; CHECK-O-NEXT: Running analysis: AAManager
 ; CHECK-O-NEXT: Running analysis: BasicAA
diff --git a/llvm/test/Other/new-pm-thinlto-postlink-samplepgo-defaults.ll b/llvm/test/Other/new-pm-thinlto-postlink-samplepgo-defaults.ll
index 62b81ac7cad03f..d375747547d61f 100644
--- a/llvm/test/Other/new-pm-thinlto-postlink-samplepgo-defaults.ll
+++ b/llvm/test/Other/new-pm-thinlto-postlink-samplepgo-defaults.ll
@@ -48,6 +48,7 @@
 ; CHECK-O-NEXT: Running analysis: TargetLibraryAnalysis
 ; CHECK-O-NEXT: Running pass: PromotePass
 ; CHECK-O-NEXT: Running pass: InstCombinePass
+; CHECK-O-NEXT: Running analysis: LastRunTrackingAnalysis
 ; CHECK-O-NEXT: Running analysis: AAManager on foo
 ; CHECK-O-NEXT: Running analysis: BasicAA
 ; CHECK-O-NEXT: Running analysis: ScopedNoAliasAA
diff --git a/llvm/test/Other/new-pm-thinlto-prelink-defaults.ll b/llvm/test/Other/new-pm-thinlto-prelink-defaults.ll
index ab04f80abc5722..5aacd26def2be5 100644
--- a/llvm/test/Other/new-pm-thinlto-prelink-defaults.ll
+++ b/llvm/test/Other/new-pm-thinlto-prelink-defaults.ll
@@ -86,6 +86,7 @@
 ; CHECK-O-NEXT: Running pass: GlobalOptPass
 ; CHECK-O-NEXT: Running pass: PromotePass
 ; CHECK-O-NEXT: Running pass: InstCombinePass
+; CHECK-O-NEXT: Running analysis: LastRunTrackingAnalysis
 ; CHECK-O-NEXT: Running analysis: OptimizationRemarkEmitterAnalysis
 ; CHECK-O-NEXT: Running analysis: AAManager
 ; CHECK-O-NEXT: Running analysis: BasicAA
diff --git a/llvm/test/Other/new-pm-thinlto-prelink-pgo-defaults.ll b/llvm/test/Other/new-pm-thinlto-prelink-pgo-defaults.ll
index c5fc4d57539c5f..f6a94065968038 100644
--- a/llvm/test/Other/new-pm-thinlto-prelink-pgo-defaults.ll
+++ b/llvm/test/Other/new-pm-thinlto-prelink-pgo-defaults.ll
@@ -50,6 +50,7 @@
 ; CHECK-O-NEXT: Running pass: GlobalOptPass
 ; CHECK-O-NEXT: Running pass: PromotePass
 ; CHECK-O-NEXT: Running pass: InstCombinePass
+; CHECK-O-NEXT: Running analysis: LastRunTrackingAnalysis
 ; CHECK-O-NEXT: Running analysis: OptimizationRemarkEmitterAnalysis
 ; CHECK-O-NEXT: Running analysis: AAManager
 ; CHECK-O-NEXT: Running analysis: BasicAA
@@ -122,6 +123,7 @@
 ; CHECK-O23SZ-NEXT: Invalidating analysis: LazyValueAnalysis
 ; CHECK-O-NEXT: Running pass: SimplifyCFGPass
 ; CHECK-O-NEXT: Running pass: InstCombinePass
+; CHECK-O-NEXT: Running analysis: LastRunTrackingAnalysis
 ; CHECK-O-NEXT: Running analysis: BlockFrequencyAnalysis on foo
 ; CHECK-O-NEXT: Running analysis: BranchProbabilityAnalysis on foo
 ; CHECK-O-NEXT: Running analysis: LoopAnalysis on foo
diff --git a/llvm/test/Other/new-pm-thinlto-prelink-samplepgo-defaults.ll b/llvm/test/Other/new-pm-thinlto-prelink-samplepgo-defaults.ll
index 096110f775b04f..48a9433d249996 100644
--- a/llvm/test/Other/new-pm-thinlto-prelink-samplepgo-defaults.ll
+++ b/llvm/test/Other/new-pm-thinlto-prelink-samplepgo-defaults.ll
@@ -53,6 +53,7 @@
 ; CHECK-O-NEXT: Running pass: GlobalOptPass
 ; CHECK-O-NEXT: Running pass: PromotePass
 ; CHECK-O-NEXT: Running pass: InstCombinePass
+; CHECK-O-NEXT: Running analysis: LastRunTrackingAnalysis
 ; CHECK-O-NEXT: Running analysis: OptimizationRemarkEmitterAnalysis on foo
 ; CHECK-O-NEXT: Running analysis: AAManager on foo
 ; CHECK-O-NEXT: Running analysis: BasicAA
diff --git a/llvm/test/Transforms/Coroutines/coro-retcon-opaque-ptr.ll b/llvm/test/Transforms/Coroutines/coro-retcon-opaque-ptr.ll
index f456b6e7bc8583..1908b31f52db39 100644
--- a/llvm/test/Transforms/Coroutines/coro-retcon-opaque-ptr.ll
+++ b/llvm/test/Transforms/Coroutines/coro-retcon-opaque-ptr.ll
@@ -33,9 +33,11 @@ cleanup:                                          ; preds = %loop
 define i32 @main() {
 ; CHECK-LABEL: @main(
 ; CHECK-NEXT:  entry:
-; CHECK-NEXT:    call void @print(i32 4)
-; CHECK-NEXT:    call void @print(i32 5), !noalias !0
-; CHECK-NEXT:    call void @print(i32 6), !noalias !3
+; CHECK-NEXT:    tail call void @print(i32 4)
+; CHECK-NEXT:    tail call void @llvm.experimental.noalias.scope.decl(metadata [[META0:![0-9]+]])
+; CHECK-NEXT:    tail call void @print(i32 5), !noalias [[META0]]
+; CHECK-NEXT:    tail call void @llvm.experimental.noalias.scope.decl(metadata [[META3:![0-9]+]])
+; CHECK-NEXT:    tail call void @print(i32 6), !noalias [[META3]]
 ; CHECK-NEXT:    ret i32 0
 ;
 entry:
diff --git a/llvm/test/Transforms/Coroutines/coro-retcon.ll b/llvm/test/Transforms/Coroutines/coro-retcon.ll
index b12a646ef53f9f..e0484c6d669410 100644
--- a/llvm/test/Transforms/Coroutines/coro-retcon.ll
+++ b/llvm/test/Transforms/Coroutines/coro-retcon.ll
@@ -43,8 +43,10 @@ define i32 @main() {
 ; CHECK-LABEL: @main(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    tail call void @print(i32 4)
-; CHECK-NEXT:    tail call void @print(i32 5), !noalias !0
-; CHECK-NEXT:    tail call void @print(i32 6), !noalias !3
+; CHECK-NEXT:    tail call void @llvm.experimental.noalias.scope.decl(metadata [[META0:![0-9]+]])
+; CHECK-NEXT:    tail call void @print(i32 5), !noalias [[META0]]
+; CHECK-NEXT:    tail call void @llvm.experimental.noalias.scope.decl(metadata [[META3:![0-9]+]])
+; CHECK-NEXT:    tail call void @print(i32 6), !noalias [[META3]]
 ; CHECK-NEXT:    ret i32 0
 ;
 ; CORO-LABEL: @main(
diff --git a/llvm/unittests/Target/X86/TernlogTest.cpp b/llvm/unittests/Target/X86/TernlogTest.cpp
index b5be97334bd981..34bd0b1fc543a7 100644
--- a/llvm/unittests/Target/X86/TernlogTest.cpp
+++ b/llvm/unittests/Target/X86/TernlogTest.cpp
@@ -155,6 +155,7 @@ struct TernTester {
     Function *F = M->getFunction("foo");
     ASSERT_TRUE(F);
     ASSERT_EQ(F->getInstructionCount(), 2u);
+    FAM.clear();
     FPM.run(*F, FAM);
     ASSERT_EQ(F->getInstructionCount(), 1u);
     ASSERT_EQ(F->size(), 1u);

>From 079ecdba7da6b914b995f82a1fc05520f98c997f Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Sun, 13 Oct 2024 12:05:42 +0800
Subject: [PATCH 5/7] [Analysis] Add statistics

---
 llvm/lib/Analysis/LastRunTrackingAnalysis.cpp | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Analysis/LastRunTrackingAnalysis.cpp b/llvm/lib/Analysis/LastRunTrackingAnalysis.cpp
index 598a6cec9a06d0..9add9a598f2b03 100644
--- a/llvm/lib/Analysis/LastRunTrackingAnalysis.cpp
+++ b/llvm/lib/Analysis/LastRunTrackingAnalysis.cpp
@@ -13,10 +13,15 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/Analysis/LastRunTrackingAnalysis.h"
+#include "llvm/ADT/Statistic.h"
 #include "llvm/Support/CommandLine.h"
 
 using namespace llvm;
 
+#define DEBUG_TYPE "last-run-tracking"
+STATISTIC(NumSkippedPasses, "Number of skipped passes");
+STATISTIC(NumLRTQueries, "Number of LastRunTracking queries");
+
 static cl::opt<bool>
     DisableLastRunTracking("disable-last-run-tracking", cl::Hidden,
                            cl::desc("Disable last run tracking"),
@@ -25,10 +30,15 @@ static cl::opt<bool>
 bool LastRunTrackingInfo::shouldSkipImpl(PassID ID, OptionPtr Ptr) const {
   if (DisableLastRunTracking)
     return false;
+  ++NumLRTQueries;
   auto Iter = TrackedPasses.find(ID);
   if (Iter == TrackedPasses.end())
     return false;
-  return !Iter->second || Iter->second(Ptr);
+  if (!Iter->second || Iter->second(Ptr)) {
+    ++NumSkippedPasses;
+    return true;
+  }
+  return false;
 }
 
 void LastRunTrackingInfo::updateImpl(PassID ID, bool Changed,

>From 64134cf07ea7eb39c60320087c0c5afdc16c3a2b Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Sun, 13 Oct 2024 12:44:46 +0800
Subject: [PATCH 6/7] [Analysis] Add unittests

---
 llvm/unittests/Analysis/CMakeLists.txt        |   1 +
 .../Analysis/LastRunTrackingAnalysisTest.cpp  | 117 ++++++++++++++++++
 2 files changed, 118 insertions(+)
 create mode 100644 llvm/unittests/Analysis/LastRunTrackingAnalysisTest.cpp

diff --git a/llvm/unittests/Analysis/CMakeLists.txt b/llvm/unittests/Analysis/CMakeLists.txt
index a3f4c10fcb9ad2..76d16513d93417 100644
--- a/llvm/unittests/Analysis/CMakeLists.txt
+++ b/llvm/unittests/Analysis/CMakeLists.txt
@@ -33,6 +33,7 @@ set(ANALYSIS_TEST_SOURCES
   InlineCostTest.cpp
   IRSimilarityIdentifierTest.cpp
   IVDescriptorsTest.cpp
+  LastRunTrackingAnalysisTest.cpp
   LazyCallGraphTest.cpp
   LoadsTest.cpp
   LoopInfoTest.cpp
diff --git a/llvm/unittests/Analysis/LastRunTrackingAnalysisTest.cpp b/llvm/unittests/Analysis/LastRunTrackingAnalysisTest.cpp
new file mode 100644
index 00000000000000..37b9d1edbf29d2
--- /dev/null
+++ b/llvm/unittests/Analysis/LastRunTrackingAnalysisTest.cpp
@@ -0,0 +1,117 @@
+//===--- LastRunTrackingAnalysisTest.cpp - LastRunTrackingAnalysis tests---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Analysis/LastRunTrackingAnalysis.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Passes/PassBuilder.h"
+#include "gtest/gtest.h"
+
+namespace {
+
+using namespace llvm;
+
+class LastRunTrackingAnalysisTest : public testing::Test {
+protected:
+  LLVMContext C;
+  Module M;
+  PassBuilder PB;
+
+  LoopAnalysisManager LAM;
+  FunctionAnalysisManager FAM;
+  CGSCCAnalysisManager CGAM;
+  ModulePassManager MPM;
+  ModuleAnalysisManager MAM;
+
+  LastRunTrackingAnalysisTest() : M("LastRunTrackingAnalysisTest", C) {
+    PB.registerModuleAnalyses(MAM);
+    PB.registerCGSCCAnalyses(CGAM);
+    PB.registerFunctionAnalyses(FAM);
+    PB.registerLoopAnalyses(LAM);
+    PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
+  }
+};
+
+struct PassOption final {
+  uint32_t Threshold;
+
+  /// Assume that this pass doesn't make changes with threshold A if we already
+  /// know it doesn't make changes with a larger threshold B.
+  bool isCompatibleWith(const PassOption &LastOpt) const {
+    return Threshold <= LastOpt.Threshold;
+  }
+};
+
+class ModuleNoopPass : public PassInfoMixin<ModuleNoopPass> {
+  uint32_t &ExecutedBitMap;
+  uint32_t RunID;
+  void *PassID;
+  bool ShouldChange;
+  std::optional<PassOption> Option;
+
+  bool shouldSkip(LastRunTrackingInfo &LRT) {
+    if (Option.has_value())
+      return LRT.shouldSkip(PassID, *Option);
+    return LRT.shouldSkip(PassID);
+  }
+
+  void update(LastRunTrackingInfo &LRT) {
+    if (Option.has_value())
+      return LRT.update(PassID, ShouldChange, *Option);
+    return LRT.update(PassID, ShouldChange);
+  }
+
+public:
+  explicit ModuleNoopPass(uint32_t &ExecutedBitMapRef, uint32_t RunIDVal,
+                          void *PassIDVal, bool ShouldChangeVal,
+                          std::optional<PassOption> OptionVal = std::nullopt)
+      : ExecutedBitMap(ExecutedBitMapRef), RunID(RunIDVal), PassID(PassIDVal),
+        ShouldChange(ShouldChangeVal), Option(OptionVal) {}
+
+  PreservedAnalyses run(Module &F, ModuleAnalysisManager &AM) {
+    auto &LRT = AM.getResult<LastRunTrackingAnalysis>(F);
+    if (shouldSkip(LRT)) {
+      EXPECT_FALSE(ShouldChange) << "This pass is incorrectly skipped.";
+      return PreservedAnalyses::all();
+    }
+    ExecutedBitMap |= 1U << RunID;
+    update(LRT);
+    PreservedAnalyses PA;
+    PA.preserve<LastRunTrackingAnalysis>();
+    return PA;
+  }
+};
+
+static char PassA, PassB;
+
+TEST_F(LastRunTrackingAnalysisTest, SkipTest) {
+  uint32_t BitMap = 0;
+  // Executed. This is first run of PassA.
+  MPM.addPass(ModuleNoopPass(BitMap, 0, &PassA, true));
+  // Skipped since PassA has just been executed.
+  MPM.addPass(ModuleNoopPass(BitMap, 1, &PassA, false));
+  // Skipped since PassA has just been executed.
+  MPM.addPass(ModuleNoopPass(BitMap, 2, &PassA, false));
+  // Executed. This is first run of PassB.
+  MPM.addPass(ModuleNoopPass(BitMap, 3, &PassB, false, PassOption{2}));
+  // Skipped. PassB doesn't make changes with lower threshold.
+  MPM.addPass(ModuleNoopPass(BitMap, 4, &PassB, false, PassOption{1}));
+  // Executed. PassB may make changes with higher threshold.
+  MPM.addPass(ModuleNoopPass(BitMap, 5, &PassB, false, PassOption{3}));
+  // Skipped. We don't make changes since last run of PassA.
+  MPM.addPass(ModuleNoopPass(BitMap, 6, &PassA, false));
+  // Executed. PassB may make changes with higher threshold.
+  MPM.addPass(ModuleNoopPass(BitMap, 7, &PassB, true, PassOption{4}));
+  // Executed. This module has been modified by PassB.
+  MPM.addPass(ModuleNoopPass(BitMap, 8, &PassA, false));
+  MPM.run(M, MAM);
+
+  ASSERT_EQ(BitMap, 0b110101001);
+}
+
+} // namespace

>From 11306bbca19e25e9c56d9e1b0c2ea1cea4930826 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Mon, 14 Oct 2024 18:22:06 +0800
Subject: [PATCH 7/7] [InstCombine] Adjust `isCompatibleWith`

---
 llvm/include/llvm/Transforms/InstCombine/InstCombine.h | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/llvm/include/llvm/Transforms/InstCombine/InstCombine.h b/llvm/include/llvm/Transforms/InstCombine/InstCombine.h
index 5203f4cfeb976b..fcc926c31a0253 100644
--- a/llvm/include/llvm/Transforms/InstCombine/InstCombine.h
+++ b/llvm/include/llvm/Transforms/InstCombine/InstCombine.h
@@ -44,11 +44,10 @@ struct InstCombineOptions {
     return *this;
   }
 
-  /// Only enable skipping in standard optimization pipeline.
+  /// Only enable skipping when two versions of parameters are exactly the same.
   bool isCompatibleWith(const InstCombineOptions &LastOption) const {
-    return !VerifyFixpoint && !LastOption.VerifyFixpoint &&
-           MaxIterations == InstCombineDefaultMaxIterations &&
-           LastOption.MaxIterations == InstCombineDefaultMaxIterations;
+    return VerifyFixpoint == LastOption.VerifyFixpoint &&
+           MaxIterations == LastOption.MaxIterations;
   }
 };
 



More information about the llvm-commits mailing list