Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix issue with running the same PassManager twice #92823

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

modiking
Copy link
Contributor

@modiking modiking commented May 20, 2024

Fixes #58939 by re-initializing the moved from passmanagers in the inliner

Testing:
ninja check with new test

@llvmbot
Copy link
Collaborator

llvmbot commented May 20, 2024

@llvm/pr-subscribers-llvm-transforms

Author: None (modiking)

Changes

Fix by re-initializing the moved from passmanagers in the inliner

Testing:
ninja check with new test


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

2 Files Affected:

  • (modified) llvm/lib/Transforms/IPO/Inliner.cpp (+5)
  • (modified) llvm/unittests/CodeGen/PassManagerTest.cpp (+24)
diff --git a/llvm/lib/Transforms/IPO/Inliner.cpp b/llvm/lib/Transforms/IPO/Inliner.cpp
index a9747aebf67bb..33aeee4a0d100 100644
--- a/llvm/lib/Transforms/IPO/Inliner.cpp
+++ b/llvm/lib/Transforms/IPO/Inliner.cpp
@@ -628,6 +628,11 @@ PreservedAnalyses ModuleInlinerWrapperPass::run(Module &M,
         createDevirtSCCRepeatedPass(std::move(PM), MaxDevirtIterations)));
 
   MPM.addPass(std::move(AfterCGMPM));
+
+  // If this is run again (e.g. same PassManager invoked twice)
+  // these need to be re-initialized after being moved.
+  PM = CGSCCPassManager();
+  AfterCGMPM = ModulePassManager();
   MPM.run(M, MAM);
 
   // Discard the InlineAdvisor, a subsequent inlining session should construct
diff --git a/llvm/unittests/CodeGen/PassManagerTest.cpp b/llvm/unittests/CodeGen/PassManagerTest.cpp
index d3a410f5450cc..8905ee7e1b338 100644
--- a/llvm/unittests/CodeGen/PassManagerTest.cpp
+++ b/llvm/unittests/CodeGen/PassManagerTest.cpp
@@ -264,4 +264,28 @@ TEST_F(PassManagerTest, DiagnosticHandler) {
               std::string::npos);
 }
 
+TEST_F(PassManagerTest, RunTwice) {
+  if (!TM)
+    GTEST_SKIP();
+
+  M->setDataLayout(TM->createDataLayout());
+
+  LoopAnalysisManager LAM;
+  FunctionAnalysisManager FAM;
+  CGSCCAnalysisManager CGAM;
+  ModuleAnalysisManager MAM;
+  PassBuilder PB(TM.get());
+  PB.registerModuleAnalyses(MAM);
+  PB.registerCGSCCAnalyses(CGAM);
+  PB.registerFunctionAnalyses(FAM);
+  PB.registerLoopAnalyses(LAM);
+  PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
+
+  ModulePassManager MPM;
+  MPM.addPass(PB.buildPerModuleDefaultPipeline(OptimizationLevel::O2));
+
+  MPM.run(*M, MAM);
+  MPM.run(*M, MAM);
+}
+
 } // namespace

@modiking modiking changed the title Fix issue with running the same PassManager twice (58939) Fix issue with running the same PassManager twice (https://github.com/llvm/llvm-project/issues/58939) May 20, 2024
@modiking modiking changed the title Fix issue with running the same PassManager twice (https://github.com/llvm/llvm-project/issues/58939) Fix issue with running the same PassManager twice May 20, 2024
Copy link
Contributor

@aeubanks aeubanks left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this isn't the right solution. if we're calling ModuleInlinerWrapperPass::run() more than once, we're going to keep adding random passes/sub-pass managers to MPM and running those.

we really shouldn't be creating and running pass managers within a run(). could you see if we could somehow make it so we do all the pass management once? will probably involve modifying PassBuilderPipelines.cpp

@@ -264,4 +264,28 @@ TEST_F(PassManagerTest, DiagnosticHandler) {
std::string::npos);
}

TEST_F(PassManagerTest, RunTwice) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

put this in llvm/unittests/IR/PassManagerTest.cpp instead

@modiking
Copy link
Contributor Author

modiking commented May 20, 2024

this isn't the right solution. if we're calling ModuleInlinerWrapperPass::run() more than once, we're going to keep adding random passes/sub-pass managers to MPM and running those.

we really shouldn't be creating and running pass managers within a run(). could you see if we could somehow make it so we do all the pass management once? will probably involve modifying PassBuilderPipelines.cpp

Yeah it really is strange that a pass contains pass managers. I don't have too much context here but reading through what MIWP does it seems to be a pass manager in every aspect expect being a PassManager. It looks like a distinction is that MIWP executes a PassManager at pass runtime which depending on it's internal state:

  if (MaxDevirtIterations == 0)
    MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(PM)));
  else
    MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(
        createDevirtSCCRepeatedPass(std::move(PM), MaxDevirtIterations)));

But given MaxDevirtIterations is const this isn't really a runtime decision. It seems like MIWP can be replaced with a regular MPM and the decision above be made at pipeline construction. Is that the direction you're suggesting?

@aeubanks
Copy link
Contributor

But given MaxDevirtIterations is const this isn't really a runtime decision. It seems like MIWP can be replaced with a regular MPM and the decision above be made at pipeline construction. Is that the direction you're suggesting?

Yes, exactly

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[llvm] Crash when running new PassManager on multiple modules
3 participants