Author: dalmurii Date: 2025-08-29T08:21:08-07:00 New Revision: f4665b7825c875f8d79c30642b3f1989f0ade0ee
URL: https://github.com/llvm/llvm-project/commit/f4665b7825c875f8d79c30642b3f1989f0ade0ee DIFF: https://github.com/llvm/llvm-project/commit/f4665b7825c875f8d79c30642b3f1989f0ade0ee.diff LOG: Singleton hack of fixing static initialisation order fiasco (#154541) https://github.com/llvm/llvm-project/issues/154528 # Brief Indirect linking of llvm as a shared library is causing a "free() invalid size abortion". In my case, my project depends on google/clspv which in turn pulls `llvm`. Note that the issue does not occur when `clspv` and `llvm` is all statically linked. # Structure of a project which might be causing an error [google/clspv](https://github.com/google/clspv) has been depending on this project (llvm-project), as a static library. My personal project has been depending on [google/clspv](https://github.com/google/clspv) as a shared library. So `MyProject` was linked to shared object `clspv_core.so` which is containing `llvm-project` as its component. # Problem Linking `llvm-project` indirectly to `MyProject` via `clspv_core` was causing the `free() invalid size` abortion. > When library is all statically linked, this problem did not occur. [This issue](https://github.com/llvm/llvm-project/issues/154528) has a full log of the programme running with valgrind. # Reason in my expectation `KnownAssumptionStrings` from [clang/lib/Sema/SemaOpenMP.cpp](https://github.com/llvm/llvm-project/pull/154541/files#diff-032b46da5a8b94f6d8266072e296726c361066e32139024c86dcba5bf64960fc), [llvm/include/llvm/IR/Assumptions.h](https://github.com/llvm/llvm-project/pull/154541/files#diff-ebb09639e5957c2e4d27be9dcb1b1475da67d88db829d24ed8039f351a63ccff), [llvm/lib/IR/Assumptions.cpp](https://github.com/llvm/llvm-project/pull/154541/files#diff-1b490dd29304c875364871e35e1cc8e47bf71898affe3a4dbde6eb91c4016d06) and `FeatureMap` from [llvm/lib/Analysis/MLInlineAdvisor.cpp](https://github.com/llvm/llvm-project/pull/154541/files#diff-26c738eb291410ed83595a4162de617e8cbebddb46331f56d39d193868e29857), [llvm/include/llvm/Analysis/InlineModelFeatureMaps.h](https://github.com/llvm/llvm-project/pull/154541/files#diff-3b5a3359b2a0784186fb3f90dfabf905e8640b6adfd7d2c75259a6835751a6a7) which have been placed on global scope, causing static initialisation order ficasso when indirectly linked by `Myproject`. # Fix trial Changing those global instances I've mentioned ~ `KnownAssumptionStrings` and `FeatureMap` ~ to functions which return a static variable's left value ~ `getKnownAssumptionStrings()`, `getFeatureMap()` ~ has solved my personal problem, so I am pulling a request of it. Added: Modified: clang/lib/Sema/SemaOpenMP.cpp llvm/include/llvm/Analysis/InlineModelFeatureMaps.h llvm/include/llvm/IR/Assumptions.h llvm/lib/Analysis/MLInlineAdvisor.cpp llvm/lib/IR/Assumptions.cpp Removed: ################################################################################ diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index bbf2b2ac69d66..4b030a265fa66 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -24834,12 +24834,12 @@ ExprResult SemaOpenMP::ActOnOMPIteratorExpr(Scope *S, /// Check if \p AssumptionStr is a known assumption and warn if not. static void checkOMPAssumeAttr(Sema &S, SourceLocation Loc, StringRef AssumptionStr) { - if (llvm::KnownAssumptionStrings.count(AssumptionStr)) + if (llvm::getKnownAssumptionStrings().count(AssumptionStr)) return; unsigned BestEditDistance = 3; StringRef Suggestion; - for (const auto &KnownAssumptionIt : llvm::KnownAssumptionStrings) { + for (const auto &KnownAssumptionIt : llvm::getKnownAssumptionStrings()) { unsigned EditDistance = AssumptionStr.edit_distance(KnownAssumptionIt.getKey()); if (EditDistance < BestEditDistance) { diff --git a/llvm/include/llvm/Analysis/InlineModelFeatureMaps.h b/llvm/include/llvm/Analysis/InlineModelFeatureMaps.h index 25a35df3efe2c..5c6aee3ab38ab 100644 --- a/llvm/include/llvm/Analysis/InlineModelFeatureMaps.h +++ b/llvm/include/llvm/Analysis/InlineModelFeatureMaps.h @@ -160,7 +160,7 @@ inlineCostFeatureToMlFeature(InlineCostFeatureIndex Feature) { return static_cast<FeatureIndex>(static_cast<size_t>(Feature)); } -LLVM_ABI extern std::vector<TensorSpec> FeatureMap; +LLVM_ABI extern std::vector<TensorSpec> &getFeatureMap(); LLVM_ABI extern const char *const DecisionName; LLVM_ABI extern const TensorSpec InlineDecisionSpec; diff --git a/llvm/include/llvm/IR/Assumptions.h b/llvm/include/llvm/IR/Assumptions.h index f1663f3d6d2bd..ebc55921e73d3 100644 --- a/llvm/include/llvm/IR/Assumptions.h +++ b/llvm/include/llvm/IR/Assumptions.h @@ -30,18 +30,18 @@ constexpr StringRef AssumptionAttrKey = "llvm.assume"; /// A set of known assumption strings that are accepted without warning and /// which can be recommended as typo correction. -LLVM_ABI extern StringSet<> KnownAssumptionStrings; +LLVM_ABI extern StringSet<> &getKnownAssumptionStrings(); /// Helper that allows to insert a new assumption string in the known assumption /// set by creating a (static) object. struct KnownAssumptionString { KnownAssumptionString(const char *AssumptionStr) : AssumptionStr(AssumptionStr) { - KnownAssumptionStrings.insert(AssumptionStr); + getKnownAssumptionStrings().insert(AssumptionStr); } KnownAssumptionString(StringRef AssumptionStr) : AssumptionStr(AssumptionStr) { - KnownAssumptionStrings.insert(AssumptionStr); + getKnownAssumptionStrings().insert(AssumptionStr); } operator StringRef() const { return AssumptionStr; } diff --git a/llvm/lib/Analysis/MLInlineAdvisor.cpp b/llvm/lib/Analysis/MLInlineAdvisor.cpp index 8853a13972bea..7854c19088ad3 100644 --- a/llvm/lib/Analysis/MLInlineAdvisor.cpp +++ b/llvm/lib/Analysis/MLInlineAdvisor.cpp @@ -27,6 +27,7 @@ #include "llvm/Analysis/ProfileSummaryInfo.h" #include "llvm/Analysis/ReleaseModeModelRunner.h" #include "llvm/Analysis/TargetTransformInfo.h" +#include "llvm/Analysis/TensorSpec.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/InstIterator.h" #include "llvm/IR/Module.h" @@ -77,10 +78,10 @@ llvm::getReleaseModeAdvisor(Module &M, ModuleAnalysisManager &MAM, std::unique_ptr<MLModelRunner> AOTRunner; if (InteractiveChannelBaseName.empty()) AOTRunner = std::make_unique<ReleaseModeModelRunner<CompiledModelType>>( - M.getContext(), FeatureMap, DecisionName, + M.getContext(), getFeatureMap(), DecisionName, EmbeddedModelRunnerOptions().setModelSelector(ModelSelector)); else { - auto Features = FeatureMap; + auto Features = getFeatureMap(); if (InteractiveIncludeDefault) Features.push_back(DefaultDecisionSpec); AOTRunner = std::make_unique<InteractiveModelRunner>( @@ -106,8 +107,9 @@ static cl::opt<bool> KeepFPICache( "For test - keep the ML Inline advisor's FunctionPropertiesInfo cache"), cl::init(false)); -// clang-format off -std::vector<TensorSpec> llvm::FeatureMap{ +std::vector<TensorSpec> &llvm::getFeatureMap() { + // clang-format off +static std::vector<TensorSpec> FeatureMap{ #define POPULATE_NAMES(DTYPE, SHAPE, NAME, __) TensorSpec::createSpec<DTYPE>(#NAME, SHAPE), // InlineCost features - these must come first INLINE_COST_FEATURE_ITERATOR(POPULATE_NAMES) @@ -116,7 +118,9 @@ std::vector<TensorSpec> llvm::FeatureMap{ INLINE_FEATURE_ITERATOR(POPULATE_NAMES) #undef POPULATE_NAMES }; -// clang-format on + // clang-format on + return FeatureMap; +} const char *const llvm::DecisionName = "inlining_decision"; const TensorSpec llvm::InlineDecisionSpec = @@ -195,9 +199,9 @@ MLInlineAdvisor::MLInlineAdvisor( } // Add the IR2Vec features to the feature map auto IR2VecDim = IR2VecVocabResult->getDimension(); - FeatureMap.push_back( + getFeatureMap().push_back( TensorSpec::createSpec<float>("callee_embedding", {IR2VecDim})); - FeatureMap.push_back( + getFeatureMap().push_back( TensorSpec::createSpec<float>("caller_embedding", {IR2VecDim})); } } @@ -471,7 +475,8 @@ std::unique_ptr<InlineAdvice> MLInlineAdvisor::getAdviceImpl(CallBase &CB) { } // This one would have been set up to be right at the end. if (!InteractiveChannelBaseName.empty() && InteractiveIncludeDefault) - *ModelRunner->getTensor<int64_t>(FeatureMap.size()) = GetDefaultAdvice(CB); + *ModelRunner->getTensor<int64_t>(getFeatureMap().size()) = + GetDefaultAdvice(CB); return getAdviceFromModel(CB, ORE); } @@ -549,8 +554,8 @@ void MLInlineAdvice::reportContextForRemark( DiagnosticInfoOptimizationBase &OR) { using namespace ore; OR << NV("Callee", Callee->getName()); - for (size_t I = 0; I < FeatureMap.size(); ++I) - OR << NV(FeatureMap[I].name(), + for (size_t I = 0; I < getFeatureMap().size(); ++I) + OR << NV(getFeatureMap()[I].name(), *getAdvisor()->getModelRunner().getTensor<int64_t>(I)); OR << NV("ShouldInline", isInliningRecommended()); } diff --git a/llvm/lib/IR/Assumptions.cpp b/llvm/lib/IR/Assumptions.cpp index 6adbbc4a63b0a..f8bbcb32231cb 100644 --- a/llvm/lib/IR/Assumptions.cpp +++ b/llvm/lib/IR/Assumptions.cpp @@ -101,12 +101,16 @@ bool llvm::addAssumptions(CallBase &CB, return ::addAssumptionsImpl(CB, Assumptions); } -StringSet<> llvm::KnownAssumptionStrings({ - "omp_no_openmp", // OpenMP 5.1 - "omp_no_openmp_routines", // OpenMP 5.1 - "omp_no_parallelism", // OpenMP 5.1 - "omp_no_openmp_constructs", // OpenMP 6.0 - "ompx_spmd_amenable", // OpenMPOpt extension - "ompx_no_call_asm", // OpenMPOpt extension - "ompx_aligned_barrier", // OpenMPOpt extension -}); +StringSet<> &llvm::getKnownAssumptionStrings() { + static StringSet<> Object({ + "omp_no_openmp", // OpenMP 5.1 + "omp_no_openmp_routines", // OpenMP 5.1 + "omp_no_parallelism", // OpenMP 5.1 + "omp_no_openmp_constructs", // OpenMP 6.0 + "ompx_spmd_amenable", // OpenMPOpt extension + "ompx_no_call_asm", // OpenMPOpt extension + "ompx_aligned_barrier", // OpenMPOpt extension + }); + + return Object; +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits