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.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
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.