forked from OSchip/llvm-project
[FuncSpec] Invalidate analyses when deleting a fully specialised function
Deleting a fully specialised function left dangling pointers in `FunctionAnalysisManager`, which causes an internal compiler error when the function's storage was reused. Fixes bug #58759. Reviewed By: ChuanqiXu Differential Revision: https://reviews.llvm.org/D138909 Change-Id: Ifed378c748af35e8fe7dcbdddb0f41b8777cbe87
This commit is contained in:
parent
c0692c08ee
commit
e7ed43c753
|
@ -45,7 +45,7 @@ bool runIPSCCP(Module &M, const DataLayout &DL,
|
|||
function_ref<AnalysisResultsForFn(Function &)> getAnalysis);
|
||||
|
||||
bool runFunctionSpecialization(
|
||||
Module &M, const DataLayout &DL,
|
||||
Module &M, FunctionAnalysisManager *FAM, const DataLayout &DL,
|
||||
std::function<TargetLibraryInfo &(Function &)> GetTLI,
|
||||
std::function<TargetTransformInfo &(Function &)> GetTTI,
|
||||
std::function<AssumptionCache &(Function &)> GetAC,
|
||||
|
|
|
@ -271,6 +271,9 @@ class FunctionSpecializer {
|
|||
/// The IPSCCP Solver.
|
||||
SCCPSolver &Solver;
|
||||
|
||||
/// Analysis manager, needed to invalidate analyses.
|
||||
FunctionAnalysisManager *FAM;
|
||||
|
||||
/// Analyses used to help determine if a function should be specialized.
|
||||
std::function<AssumptionCache &(Function &)> GetAC;
|
||||
std::function<TargetTransformInfo &(Function &)> GetTTI;
|
||||
|
@ -282,11 +285,12 @@ class FunctionSpecializer {
|
|||
DenseMap<Function *, CodeMetrics> FunctionMetrics;
|
||||
|
||||
public:
|
||||
FunctionSpecializer(SCCPSolver &Solver,
|
||||
FunctionSpecializer(SCCPSolver &Solver, FunctionAnalysisManager *FAM,
|
||||
std::function<AssumptionCache &(Function &)> GetAC,
|
||||
std::function<TargetTransformInfo &(Function &)> GetTTI,
|
||||
std::function<TargetLibraryInfo &(Function &)> GetTLI)
|
||||
: Solver(Solver), GetAC(GetAC), GetTTI(GetTTI), GetTLI(GetTLI) {}
|
||||
: Solver(Solver), FAM(FAM), GetAC(GetAC), GetTTI(GetTTI), GetTLI(GetTLI) {
|
||||
}
|
||||
|
||||
~FunctionSpecializer() {
|
||||
// Eliminate dead code.
|
||||
|
@ -344,6 +348,8 @@ public:
|
|||
for (auto *F : FullySpecialized) {
|
||||
LLVM_DEBUG(dbgs() << "FnSpecialization: Removing dead function "
|
||||
<< F->getName() << "\n");
|
||||
if (FAM)
|
||||
FAM->clear(*F, F->getName());
|
||||
F->eraseFromParent();
|
||||
}
|
||||
FullySpecialized.clear();
|
||||
|
@ -819,13 +825,13 @@ private:
|
|||
} // namespace
|
||||
|
||||
bool llvm::runFunctionSpecialization(
|
||||
Module &M, const DataLayout &DL,
|
||||
Module &M, FunctionAnalysisManager *FAM, const DataLayout &DL,
|
||||
std::function<TargetLibraryInfo &(Function &)> GetTLI,
|
||||
std::function<TargetTransformInfo &(Function &)> GetTTI,
|
||||
std::function<AssumptionCache &(Function &)> GetAC,
|
||||
function_ref<AnalysisResultsForFn(Function &)> GetAnalysis) {
|
||||
SCCPSolver Solver(DL, GetTLI, M.getContext());
|
||||
FunctionSpecializer FS(Solver, GetAC, GetTTI, GetTLI);
|
||||
FunctionSpecializer FS(Solver, FAM, GetAC, GetTTI, GetTLI);
|
||||
bool Changed = false;
|
||||
|
||||
// Loop over all functions, marking arguments to those with their addresses
|
||||
|
|
|
@ -130,7 +130,7 @@ PreservedAnalyses FunctionSpecializationPass::run(Module &M,
|
|||
&FAM.getResult<LoopAnalysis>(F)};
|
||||
};
|
||||
|
||||
if (!runFunctionSpecialization(M, DL, GetTLI, GetTTI, GetAC, GetAnalysis))
|
||||
if (!runFunctionSpecialization(M, &FAM, DL, GetTLI, GetTTI, GetAC, GetAnalysis))
|
||||
return PreservedAnalyses::all();
|
||||
|
||||
PreservedAnalyses PA;
|
||||
|
@ -179,7 +179,7 @@ struct FunctionSpecializationLegacyPass : public ModulePass {
|
|||
nullptr, // manager, so set them to nullptr.
|
||||
nullptr};
|
||||
};
|
||||
return runFunctionSpecialization(M, DL, GetTLI, GetTTI, GetAC, GetAnalysis);
|
||||
return runFunctionSpecialization(M, nullptr, DL, GetTLI, GetTTI, GetAC, GetAnalysis);
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
; RUN: opt -S --passes='default<O3>' -enable-function-specialization < %s | FileCheck %s
|
||||
|
||||
define dso_local i32 @g0(i32 noundef %x) local_unnamed_addr {
|
||||
entry:
|
||||
%call = tail call fastcc i32 @f(i32 noundef %x, ptr noundef nonnull @p0)
|
||||
ret i32 %call
|
||||
}
|
||||
|
||||
define internal fastcc i32 @f(i32 noundef %x, ptr nocapture noundef readonly %p) noinline {
|
||||
entry:
|
||||
%call = tail call i32 %p(i32 noundef %x)
|
||||
%add = add nsw i32 %call, %x
|
||||
ret i32 %add
|
||||
}
|
||||
|
||||
define dso_local i32 @g1(i32 noundef %x) {
|
||||
entry:
|
||||
%call = tail call fastcc i32 @f(i32 noundef %x, ptr noundef nonnull @p1)
|
||||
ret i32 %call
|
||||
}
|
||||
|
||||
declare i32 @p0(i32 noundef)
|
||||
declare i32 @p1(i32 noundef)
|
||||
|
||||
;; Tests that `f` has been fully specialize and it didn't cause compiler crash.
|
||||
;; CHECK-DAG: f.1
|
||||
;; CHECK-DAG: f.2
|
Loading…
Reference in New Issue