27#define DEBUG_TYPE "split-module-by-category"
35struct EntryPointGroup {
37 EntryPointSet Functions;
39 EntryPointGroup() =
default;
41 EntryPointGroup(
int ID, EntryPointSet &&Functions = EntryPointSet())
42 : ID(ID), Functions(std::move(Functions)) {}
44 void clear() { Functions.clear(); }
46#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
48 constexpr size_t INDENT = 4;
50 <<
" " << ID <<
" {\n";
52 dbgs().
indent(INDENT) <<
" " <<
F->getName() <<
"\n";
63 std::unique_ptr<Module> M;
64 EntryPointGroup EntryPoints;
67 ModuleDesc(std::unique_ptr<Module> M,
68 EntryPointGroup &&EntryPoints = EntryPointGroup())
69 : M(std::move(M)), EntryPoints(std::move(EntryPoints)) {
70 assert(this->M &&
"Module should be non-null");
73 Module &getModule() {
return *M; }
74 const Module &getModule()
const {
return *M; }
76 std::unique_ptr<Module> releaseModule() {
81#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
83 dbgs() <<
"ModuleDesc[" << M->getName() <<
"] {\n";
112class DependencyGraph {
116 DependencyGraph(
const Module &M) {
120 for (
const Function &
F : M.functions()) {
122 if (
F.hasKernelCallingConv())
125 FuncTypeToFuncsMap[
F.getFunctionType()].
insert(&
F);
128 for (
const Function &
F : M.functions()) {
130 for (
const Value *U :
F.users())
140 GlobalSet &PotentialCallees = FuncTypeToFuncsMap[Signature];
141 Graph[&
F].
insert(PotentialCallees.begin(), PotentialCallees.end());
153 auto It = Graph.find(Val);
154 return (It == Graph.end())
155 ?
make_range(EmptySet.begin(), EmptySet.end())
156 :
make_range(It->second.begin(), It->second.end());
160 void addUserToGraphRecursively(
const User *Root,
const GlobalValue *V) {
166 while (!WorkList.
empty()) {
169 const Function *UFunc =
I->getFunction();
170 Graph[UFunc].insert(V);
178 if (Visited.
insert(UU).second)
190void collectFunctionsAndGlobalVariablesToExtract(
192 const EntryPointGroup &ModuleEntryPoints,
const DependencyGraph &DG) {
194 for (
const Function *
F : ModuleEntryPoints.Functions)
199 if (!GV.isDiscardableIfUnused())
205 while (Idx < GVs.
size()) {
208 for (
const GlobalValue *Dep : DG.dependencies(Obj)) {
210 if (!Func->isDeclaration())
221 EntryPointGroup &&ModuleEntryPoints) {
228 EntryPointSet NewEPs;
229 const EntryPointSet &EPs = ModuleEntryPoints.Functions;
232 ModuleEntryPoints.Functions = std::move(NewEPs);
233 return ModuleDesc{std::move(SubM), std::move(ModuleEntryPoints)};
239ModuleDesc extractCallGraph(
const Module &M,
240 EntryPointGroup &&ModuleEntryPoints,
241 const DependencyGraph &DG) {
243 collectFunctionsAndGlobalVariablesToExtract(GVs, M, ModuleEntryPoints, DG);
256class ModuleSplitter {
258 std::unique_ptr<Module> M;
259 EntryPointGroupVec
Groups;
263 EntryPointGroup drawEntryPointGroup() {
264 assert(
Groups.size() > 0 &&
"Reached end of entry point groups list.");
265 EntryPointGroup Group = std::move(
Groups.back());
271 ModuleSplitter(std::unique_ptr<Module>
Module, EntryPointGroupVec &&GroupVec)
272 : M(std::move(
Module)),
Groups(std::move(GroupVec)), DG(*M) {
273 assert(!
Groups.empty() &&
"Entry points groups collection is empty!");
278 ModuleDesc getNextSplit() {
279 return extractCallGraph(*M, drawEntryPointGroup(), DG);
283 bool hasMoreSplits()
const {
return Groups.size() > 0; }
286EntryPointGroupVec selectEntryPointGroups(
292 std::map<int, EntryPointSet> EntryPointsMap;
294 for (
const auto &
F : M.functions())
295 if (std::optional<int> Category = EPC(
F); Category)
296 EntryPointsMap[*Category].insert(&
F);
298 EntryPointGroupVec
Groups;
299 Groups.reserve(EntryPointsMap.size());
300 for (
auto &[
Key, EntryPoints] : EntryPointsMap)
301 Groups.emplace_back(
Key, std::move(EntryPoints));
309 std::unique_ptr<Module> M,
312 EntryPointGroupVec
Groups = selectEntryPointGroups(*M, EntryPointCategorizer);
313 ModuleSplitter Splitter(std::move(M), std::move(
Groups));
314 while (Splitter.hasMoreSplits()) {
315 ModuleDesc MD = Splitter.getNextSplit();
316 if (
Error E = Callback(MD.releaseModule()))
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Expand Atomic instructions
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
static SmallVector< const DIVariable *, 2 > dependencies(DbgVariable *Var)
Return all DIVariables that appear in count: expressions.
static ThreadSafeModule extractSubModule(ThreadSafeModule &TSM, StringRef Suffix, GVPredicate ShouldExtract)
Module.h This file contains the declarations for the Module class.
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallPtrSet class.
static const X86InstrFMA3Group Groups[]
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
LLVM_ABI bool isIndirectCall() const
Return true if the callsite is an indirect call.
FunctionType * getFunctionType() const
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
A Module instance is used to store all the information related to an LLVM module.
A vector that has set insertion semantics.
size_type size() const
Determine the number of elements in the SetVector.
bool contains(const_arg_type key) const
Check if the SetVector contains the given key.
bool insert(const value_type &X)
Insert a new element into the SetVector.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
LLVM Value Representation.
iterator_range< user_iterator > users()
An efficient, type-erasing, non-owning reference to a callable.
A range adaptor for a pair of iterators.
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is an optimization pass for GlobalISel generic memory operations.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
LLVM_ABI Error splitModuleTransitiveFromEntryPoints(std::unique_ptr< Module > M, function_ref< std::optional< int >(const Function &F)> EntryPointCategorizer, function_ref< Error(std::unique_ptr< Module > Part)> Callback)
Splits the given module M into parts.
ValueMap< const Value *, WeakTrackingVH > ValueToValueMapTy
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI std::unique_ptr< Module > CloneModule(const Module &M)
Return an exact copy of the specified module.