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