[llvm] [NewPM][Instrumentation] Support `MachineOptimizationRemarkEmitter` (PR #90563)

via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 29 22:42:52 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-ir

Author: None (paperchalice)

<details>
<summary>Changes</summary>

Port size remark emitter part to instrumentation. It supports both machine module pass and machine function pass, so we can remove the workaround in `MachineOutliner` in future.

---
Full diff: https://github.com/llvm/llvm-project/pull/90563.diff


5 Files Affected:

- (modified) llvm/include/llvm/IR/Module.h (+1-1) 
- (modified) llvm/include/llvm/Passes/StandardInstrumentations.h (+7) 
- (modified) llvm/lib/Passes/StandardInstrumentations.cpp (+134-1) 
- (added) llvm/test/tools/llc/new-pm/size-remark-emitter.mir (+44) 
- (modified) llvm/tools/llc/NewPMDriver.cpp (+1-1) 


``````````diff
diff --git a/llvm/include/llvm/IR/Module.h b/llvm/include/llvm/IR/Module.h
index 6135e15fd030f7..855ec4561208bd 100644
--- a/llvm/include/llvm/IR/Module.h
+++ b/llvm/include/llvm/IR/Module.h
@@ -317,7 +317,7 @@ class LLVM_EXTERNAL_VISIBILITY Module {
 
   /// Return true if size-info optimization remark is enabled, false
   /// otherwise.
-  bool shouldEmitInstrCountChangedRemark() {
+  bool shouldEmitInstrCountChangedRemark() const {
     return getContext().getDiagHandlerPtr()->isAnalysisRemarkEnabled(
         "size-info");
   }
diff --git a/llvm/include/llvm/Passes/StandardInstrumentations.h b/llvm/include/llvm/Passes/StandardInstrumentations.h
index 84d1b541171bf1..8d44d140290c91 100644
--- a/llvm/include/llvm/Passes/StandardInstrumentations.h
+++ b/llvm/include/llvm/Passes/StandardInstrumentations.h
@@ -577,6 +577,12 @@ class PrintCrashIRInstrumentation {
   static void SignalHandler(void *);
 };
 
+class InstrCountChangedReporter {
+public:
+  void registerCallbacks(PassInstrumentationCallbacks &PIC,
+                         ModuleAnalysisManager &MAM);
+};
+
 /// This class provides an interface to register all the standard pass
 /// instrumentations and manages their state (if any).
 class StandardInstrumentations {
@@ -594,6 +600,7 @@ class StandardInstrumentations {
   PrintCrashIRInstrumentation PrintCrashIR;
   IRChangedTester ChangeTester;
   VerifyInstrumentation Verify;
+  InstrCountChangedReporter EmitMFSizeRemarks;
 
   bool VerifyEach;
 
diff --git a/llvm/lib/Passes/StandardInstrumentations.cpp b/llvm/lib/Passes/StandardInstrumentations.cpp
index 63490c83e85f05..7a2248da9da99e 100644
--- a/llvm/lib/Passes/StandardInstrumentations.cpp
+++ b/llvm/lib/Passes/StandardInstrumentations.cpp
@@ -19,9 +19,13 @@
 #include "llvm/Analysis/CallGraphSCCPass.h"
 #include "llvm/Analysis/LazyCallGraph.h"
 #include "llvm/Analysis/LoopInfo.h"
+#include "llvm/Analysis/OptimizationRemarkEmitter.h"
 #include "llvm/CodeGen/MIRPrinter.h"
 #include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineFunctionAnalysis.h"
 #include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
+#include "llvm/CodeGen/MachinePassManager.h"
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/Function.h"
 #include "llvm/IR/Module.h"
@@ -48,6 +52,7 @@
 #include <vector>
 
 using namespace llvm;
+using namespace ore;
 
 static cl::opt<bool> VerifyAnalysisInvalidation("verify-analysis-invalidation",
                                                 cl::Hidden,
@@ -374,6 +379,14 @@ bool isInteresting(Any IR, StringRef PassID, StringRef PassName) {
   return true;
 }
 
+bool isMachineModulePass(StringRef PassID) {
+#define MACHINE_MODULE_PASS(NAME, CREATE_PASS)                                 \
+  if (PassID == std::remove_reference_t<decltype(CREATE_PASS)>::name())        \
+    return true;
+#include "llvm/Passes/MachinePassRegistry.def"
+  return false;
+}
+
 } // namespace
 
 template <typename T> ChangeReporter<T>::~ChangeReporter() {
@@ -1329,6 +1342,51 @@ struct PreservedModuleHashAnalysis
 
 AnalysisKey PreservedModuleHashAnalysis::Key;
 
+struct MachineInstrCounterAnalysis
+    : public AnalysisInfoMixin<MachineInstrCounterAnalysis> {
+  static AnalysisKey Key;
+
+  struct Result {
+    bool invalidate(MachineFunction &MF, const PreservedAnalyses &,
+                    MachineFunctionAnalysisManager::Invalidator &) {
+      return false;
+    }
+
+    void emitRemark(MachineFunction &MF, StringRef PassID) {
+      CountAfter = MF.getInstructionCount();
+      if (CountBefore == CountAfter)
+        return;
+
+      MachineOptimizationRemarkEmitter MORE(MF, nullptr);
+      MORE.emit([&]() {
+        int64_t Delta = static_cast<int64_t>(CountAfter) -
+                        static_cast<int64_t>(CountBefore);
+        MachineOptimizationRemarkAnalysis R("size-info", "FunctionMISizeChange",
+                                            MF.getFunction().getSubprogram(),
+                                            &MF.front());
+        R << NV("Pass", PassID)
+          << ": Function: " << NV("Function", MF.getName()) << ": "
+          << "MI Instruction count changed from "
+          << NV("MIInstrsBefore", CountBefore) << " to "
+          << NV("MIInstrsAfter", CountAfter)
+          << "; Delta: " << NV("Delta", Delta);
+        return R;
+      });
+    }
+
+    unsigned CountBefore = 0;
+    unsigned CountAfter = 0;
+  };
+
+  Result run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM) {
+    Result R;
+    R.CountBefore = MF.getInstructionCount();
+    return R;
+  }
+};
+
+AnalysisKey MachineInstrCounterAnalysis::Key;
+
 bool PreservedCFGCheckerInstrumentation::CFG::invalidate(
     Function &F, const PreservedAnalyses &PA,
     FunctionAnalysisManager::Invalidator &) {
@@ -2493,6 +2551,79 @@ void PrintCrashIRInstrumentation::registerCallbacks(
       });
 }
 
+void InstrCountChangedReporter::registerCallbacks(
+    PassInstrumentationCallbacks &PIC, ModuleAnalysisManager &MAM) {
+  PIC.registerBeforeNonSkippedPassCallback([this, &MAM, Registered = false](
+                                               StringRef PassID,
+                                               Any IR) mutable {
+    if (isIgnored(PassID))
+      return;
+    bool ShouldEmitSizeRemarks =
+        unwrapModule(IR, /*force=*/true)->shouldEmitInstrCountChangedRemark();
+    if (!ShouldEmitSizeRemarks)
+      return;
+
+    auto &MFAM = MAM.getResult<MachineFunctionAnalysisManagerModuleProxy>(
+                        const_cast<Module &>(*unwrapModule(IR)))
+                     .getManager();
+    if (!Registered) {
+      MFAM.registerPass([] { return MachineInstrCounterAnalysis(); });
+      Registered = true;
+    }
+
+    if (auto *MF =
+            const_cast<MachineFunction *>(unwrapIR<MachineFunction>(IR))) {
+      MFAM.getResult<MachineInstrCounterAnalysis>(*MF);
+      return;
+    }
+
+    // FIXME: Currently except debugify passes, `MachineOutlinerPass`
+    // is the only "machine module pass".
+    if (!isMachineModulePass(PassID))
+      return;
+    if (auto *M = const_cast<Module *>(unwrapIR<Module>(IR))) {
+      auto &FAM =
+          MAM.getResult<FunctionAnalysisManagerModuleProxy>(*M).getManager();
+      auto &MFAM = MAM.getResult<MachineFunctionAnalysisManagerModuleProxy>(*M)
+                       .getManager();
+      for (auto &F : *M) {
+        auto &MF = FAM.getResult<MachineFunctionAnalysis>(F).getMF();
+        MFAM.getResult<MachineInstrCounterAnalysis>(MF);
+      }
+    }
+  });
+
+  PIC.registerAfterPassCallback([this, &MAM](StringRef PassID, Any IR,
+                                             const PreservedAnalyses &) {
+    if (isIgnored(PassID))
+      return;
+    bool ShouldEmitSizeRemarks =
+        unwrapModule(IR, /*force=*/true)->shouldEmitInstrCountChangedRemark();
+    if (!ShouldEmitSizeRemarks)
+      return;
+
+    auto &MFAM = MAM.getResult<MachineFunctionAnalysisManagerModuleProxy>(
+                        const_cast<Module &>(*unwrapModule(IR)))
+                     .getManager();
+    if (auto *MF =
+            const_cast<MachineFunction *>(unwrapIR<MachineFunction>(IR))) {
+      MFAM.getResult<MachineInstrCounterAnalysis>(*MF).emitRemark(*MF, PassID);
+      return;
+    }
+
+    if (!isMachineModulePass(PassID))
+      return;
+    if (auto *M = const_cast<Module *>(unwrapIR<Module>(IR))) {
+      auto &FAM =
+          MAM.getResult<FunctionAnalysisManagerModuleProxy>(*M).getManager();
+      for (auto &F : *M) {
+        auto &MF = FAM.getResult<MachineFunctionAnalysis>(F).getMF();
+        MFAM.getResult<MachineInstrCounterAnalysis>(MF).emitRemark(MF, PassID);
+      }
+    }
+  });
+}
+
 void StandardInstrumentations::registerCallbacks(
     PassInstrumentationCallbacks &PIC, ModuleAnalysisManager *MAM) {
   PrintIR.registerCallbacks(PIC);
@@ -2508,8 +2639,10 @@ void StandardInstrumentations::registerCallbacks(
   WebsiteChangeReporter.registerCallbacks(PIC);
   ChangeTester.registerCallbacks(PIC);
   PrintCrashIR.registerCallbacks(PIC);
-  if (MAM)
+  if (MAM) {
     PreservedCFGChecker.registerCallbacks(PIC, *MAM);
+    EmitMFSizeRemarks.registerCallbacks(PIC, *MAM);
+  }
 
   // TimeProfiling records the pass running time cost.
   // Its 'BeforePassCallback' can be appended at the tail of all the
diff --git a/llvm/test/tools/llc/new-pm/size-remark-emitter.mir b/llvm/test/tools/llc/new-pm/size-remark-emitter.mir
new file mode 100644
index 00000000000000..f7968addad8d39
--- /dev/null
+++ b/llvm/test/tools/llc/new-pm/size-remark-emitter.mir
@@ -0,0 +1,44 @@
+# REQUIRES: x86-registered-target
+
+# RUN: llc -mtriple=x86_64-unknown-linux-gnu -filetype=null %s \
+# RUN: -p dead-mi-elimination -pass-remarks-analysis='size-info' \
+# RUN: -pass-remarks-output=%t.yaml < %s 2> %t; \
+# RUN: cat %t %t.yaml | FileCheck %s
+
+--- |
+  source_filename = "size-remark-emitter.mir"
+  target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
+  target triple = "x86_64-unknown-linux-gnu"
+  
+  define void @test() {
+  entry:
+    unreachable
+  }
+
+...
+---
+name:            test
+body:             |
+  bb.0:
+    %1:gr64 = MOV64ri 0
+    %2:gr64 = MOV64ri 0
+    $eax = COPY %1
+    RET64 implicit $eax
+...
+
+# CHECK: --- !Analysis
+# CHECK: Pass:            size-info
+# CHECK: Name:            FunctionMISizeChange
+# CHECK: Function:        test
+# CHECK: Args:
+# CHECK:   - Pass:            DeadMachineInstructionElimPass
+# CHECK:   - String:          ': Function: '
+# CHECK:   - Function:        test
+# CHECK:   - String:          ': '
+# CHECK:   - String:          'MI Instruction count changed from '
+# CHECK:   - MIInstrsBefore:  '4'
+# CHECK:   - String:          ' to '
+# CHECK:   - MIInstrsAfter:   '3'
+# CHECK:   - String:          '; Delta: '
+# CHECK:   - Delta:           '-1'
+# CHECK: ...
diff --git a/llvm/tools/llc/NewPMDriver.cpp b/llvm/tools/llc/NewPMDriver.cpp
index 6d9956ea07d356..320d02bfbc49a0 100644
--- a/llvm/tools/llc/NewPMDriver.cpp
+++ b/llvm/tools/llc/NewPMDriver.cpp
@@ -116,7 +116,6 @@ int llvm::compileModuleWithNewPM(
 
   PassInstrumentationCallbacks PIC;
   StandardInstrumentations SI(Context, Opt.DebugPM);
-  SI.registerCallbacks(PIC);
   registerCodeGenCallback(PIC, LLVMTM);
 
   MachineFunctionAnalysisManager MFAM;
@@ -124,6 +123,7 @@ int llvm::compileModuleWithNewPM(
   FunctionAnalysisManager FAM;
   CGSCCAnalysisManager CGAM;
   ModuleAnalysisManager MAM;
+  SI.registerCallbacks(PIC, &MAM);
   PassBuilder PB(Target.get(), PipelineTuningOptions(), std::nullopt, &PIC);
   PB.registerModuleAnalyses(MAM);
   PB.registerCGSCCAnalyses(CGAM);

``````````

</details>


https://github.com/llvm/llvm-project/pull/90563


More information about the llvm-commits mailing list