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) {
164 while (!WorkList.
empty()) {
167 const Function *UFunc =
I->getFunction();
168 Graph[UFunc].insert(V);
187void collectFunctionsAndGlobalVariablesToExtract(
189 const EntryPointGroup &ModuleEntryPoints,
const DependencyGraph &DG) {
191 for (
const Function *
F : ModuleEntryPoints.Functions)
196 if (!GV.isDiscardableIfUnused())
202 while (Idx < GVs.
size()) {
205 for (
const GlobalValue *Dep : DG.dependencies(Obj)) {
207 if (!Func->isDeclaration())
218 EntryPointGroup &&ModuleEntryPoints) {
225 EntryPointSet NewEPs;
226 const EntryPointSet &EPs = ModuleEntryPoints.Functions;
229 ModuleEntryPoints.Functions = std::move(NewEPs);
230 return ModuleDesc{std::move(SubM), std::move(ModuleEntryPoints)};
236ModuleDesc extractCallGraph(
const Module &M,
237 EntryPointGroup &&ModuleEntryPoints,
238 const DependencyGraph &DG) {
240 collectFunctionsAndGlobalVariablesToExtract(GVs, M, ModuleEntryPoints, DG);
253class ModuleSplitter {
255 std::unique_ptr<Module> M;
256 EntryPointGroupVec
Groups;
260 EntryPointGroup drawEntryPointGroup() {
261 assert(
Groups.size() > 0 &&
"Reached end of entry point groups list.");
262 EntryPointGroup Group = std::move(
Groups.back());
268 ModuleSplitter(std::unique_ptr<Module>
Module, EntryPointGroupVec &&GroupVec)
269 : M(std::move(
Module)),
Groups(std::move(GroupVec)), DG(*M) {
270 assert(!
Groups.empty() &&
"Entry points groups collection is empty!");
275 ModuleDesc getNextSplit() {
276 return extractCallGraph(*M, drawEntryPointGroup(), DG);
280 bool hasMoreSplits()
const {
return Groups.size() > 0; }
283EntryPointGroupVec selectEntryPointGroups(
289 std::map<int, EntryPointSet> EntryPointsMap;
291 for (
const auto &
F : M.functions())
292 if (std::optional<int> Category = EPC(
F); Category)
293 EntryPointsMap[*Category].insert(&
F);
295 EntryPointGroupVec
Groups;
296 Groups.reserve(EntryPointsMap.size());
297 for (
auto &[
Key, EntryPoints] : EntryPointsMap)
298 Groups.emplace_back(
Key, std::move(EntryPoints));
306 std::unique_ptr<Module> M,
308 function_ref<
void(std::unique_ptr<Module> Part)> Callback) {
309 EntryPointGroupVec
Groups = selectEntryPointGroups(*M, EntryPointCategorizer);
310 ModuleSplitter Splitter(std::move(M), std::move(
Groups));
311 while (Splitter.hasMoreSplits()) {
312 ModuleDesc MD = Splitter.getNextSplit();
313 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)
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.
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 void splitModuleTransitiveFromEntryPoints(std::unique_ptr< Module > M, function_ref< std::optional< int >(const Function &F)> EntryPointCategorizer, function_ref< void(std::unique_ptr< Module > Part)> Callback)
Splits the given module M into parts.
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
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.