Issue 64242
Summary Segfault in LLVMContextImpl / ValueAsMetadata
Labels
Assignees
Reporter wsmoses
    I have some code using LLVM as an API which segfaults, though have been having trouble reproducing externally as the issue is nondeterminstic otherwise.

The code runs IPSCCPPass on a module, then runs the ModuleInliner pass. This results in the LLVMContextImpl in an invalid state, such that a later call to LCSSA will segfault, though LCSSA is not the cause: https://github.com/EnzymeAD/Enzyme/issues/1361

Specifically, it appears that `IPSCCPPass` causes some ValueAsMetadata to be created, which is stored in a DenseMap<Value, ValueAsMetadata> inside the LLVMContextImpl.

The moduleInliner removes the function (and thus instruction) which is the key to that map via a dropAllReferences here: https://github.com/llvm/llvm-project/blob/09b6765e7d278a08ceece8a1e3a24fa37a35f46e/llvm/lib/Transforms/IPO/ModuleInliner.cpp#L268

Subsequent code (in my case LCSSA) that iterates through that map to lookup metadata gets bad data.

In my case, to minimize and find the source of the error I did the following:

```
+++ b/llvm/lib/Transforms/IPO/ModuleInliner.cpp
@@ -48,6 +48,17 @@ using namespace llvm;
 STATISTIC(NumInlined, "Number of functions inlined");
 STATISTIC(NumDeleted, "Number of functions deleted because all callers found");
 
+#include "/home/wmoses/llvms/llvm16/llvm/lib/IR/LLVMContextImpl.h"
+void err2(llvm::LLVMContext* C, const char* A) {
+    llvm::errs() << " <" << A << ">\n";
+  for (auto &P : C->pImpl->ValuesAsMetadata) {
+ llvm::errs() << " 0: " << *P.first << " 1: " << *P.second << "\n";
+      for (auto u: P.second->getAllArgListUsers ())
+ llvm::errs() << " + " << *u << "\n";
+  }
+    llvm::errs() << " </" << A << ">\n";
+}
+
 /// Return true if the specified inline history ID
 /// indicates an inline history that includes the specified function.
 static bool inlineHistoryIncludes(
@@ -102,6 +113,7 @@ static bool isKnownLibFunction(Function &F, TargetLibraryInfo &TLI) {
 
 PreservedAnalyses ModuleInlinerPass::run(Module &M,
 ModuleAnalysisManager &MAM) {
+ err2(&M.getContext(), "inliner pass");
   LLVM_DEBUG(dbgs() << "---- Module Inliner is Running ---- \n");
 
   auto &IAA = MAM.getResult<InlineAdvisorAnalysis>(M);
@@ -217,9 +229,11 @@ PreservedAnalyses ModuleInlinerPass::run(Module &M,
 &FAM.getResult<BlockFrequencyAnalysis>(*(CB->getCaller())),
 &FAM.getResult<BlockFrequencyAnalysis>(Callee));
 
+ err2(&M.getContext(), "preinl");
     InlineResult IR =
 InlineFunction(*CB, IFI, /*MergeAttributes=*/true,
 &FAM.getResult<AAManager>(*CB->getCaller()));
+    err2(&M.getContext(), "postinl");
     if (!IR.isSuccess()) {
 Advice->recordUnsuccessfulInlining(IR);
       continue;
@@ -258,6 +272,7 @@ PreservedAnalyses ModuleInlinerPass::run(Module &M,
     // changing inline cost thresholds.
     bool CalleeWasDeleted = false;
 if (Callee.hasLocalLinkage()) {
+      err2(&M.getContext(), "prelocalrem");
       // To check this we also need to nuke any dead constant uses (perhaps
       // made dead by this operation on other functions).
       Callee.removeDeadConstantUsers();
@@ -276,6 +291,7 @@ PreservedAnalyses ModuleInlinerPass::run(Module &M,
 DeadFunctions.push_back(&Callee);
         CalleeWasDeleted = true;
 }
+      err2(&M.getContext(), "postlocalrem");
     }
     if (CalleeWasDeleted)
       Advice->recordInliningWithCalleeDeleted();
@@ -293,8 +309,10 @@ PreservedAnalyses ModuleInlinerPass::run(Module &M,
 // Clear out any cached analyses.
     FAM.clear(*DeadF, DeadF->getName());
 
+      err2(&M.getContext(), "predeldeadf");
 // And delete the actual function from the module.
 M.getFunctionList().erase(DeadF);
+      err2(&M.getContext(), "postdeldeadf");
 
     ++N
     ```
     
     This is an error for certain on LLVM16, and may or may not occur on other versions.
_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to