50#define DEBUG_TYPE "split-module"
58bool compareClusters(
const std::pair<unsigned, unsigned> &
A,
59 const std::pair<unsigned, unsigned> &
B) {
60 if (
A.second ||
B.second)
61 return A.second >
B.second;
62 return A.first >
B.first;
65using BalancingQueueType =
66 std::priority_queue<std::pair<unsigned, unsigned>,
67 std::vector<std::pair<unsigned, unsigned>>,
68 decltype(compareClusters) *>;
74 assert((!isa<Constant>(U) || isa<GlobalValue>(U)) &&
"Bad user");
78 GVtoClusterMap.unionSets(GV,
F);
79 }
else if (
const GlobalValue *GVU = dyn_cast<GlobalValue>(U)) {
80 GVtoClusterMap.unionSets(GV, GVU);
89 for (
const auto *U : V->users()) {
92 while (!Worklist.
empty()) {
95 if (isa<Constant>(UU) && !isa<GlobalValue>(UU)) {
106 if (
const auto *GI = dyn_cast_or_null<GlobalIFunc>(GO))
107 GO = GI->getResolverFunction();
122 ClusterMapType GVtoClusterMap;
123 ComdatMembersType ComdatMembers;
125 auto recordGVSet = [&GVtoClusterMap, &ComdatMembers](
GlobalValue &GV) {
126 if (GV.isDeclaration())
130 GV.setName(
"__llvmsplit_unnamed");
136 if (
const Comdat *
C = GV.getComdat()) {
137 auto &Member = ComdatMembers[
C];
139 GVtoClusterMap.unionSets(Member, &GV);
148 GVtoClusterMap.unionSets(&GV, Root);
150 if (
const Function *
F = dyn_cast<Function>(&GV)) {
159 if (GV.hasLocalLinkage())
169 BalancingQueueType BalancingQueue(compareClusters);
171 for (
unsigned i = 0; i <
N; ++i)
172 BalancingQueue.push(std::make_pair(i, 0));
174 using SortType = std::pair<unsigned, ClusterMapType::iterator>;
181 for (ClusterMapType::iterator
I = GVtoClusterMap.begin(),
182 E = GVtoClusterMap.end();
186 std::make_pair(std::distance(GVtoClusterMap.member_begin(
I),
187 GVtoClusterMap.member_end()),
190 llvm::sort(Sets, [](
const SortType &a,
const SortType &b) {
191 if (a.first == b.first)
192 return a.second->getData()->getName() > b.second->getData()->getName();
194 return a.first > b.first;
197 for (
auto &
I : Sets) {
198 unsigned CurrentClusterID = BalancingQueue.top().first;
199 unsigned CurrentClusterSize = BalancingQueue.top().second;
200 BalancingQueue.pop();
202 LLVM_DEBUG(
dbgs() <<
"Root[" << CurrentClusterID <<
"] cluster_size("
203 <<
I.first <<
") ----> " <<
I.second->getData()->getName()
206 for (ClusterMapType::member_iterator
MI =
207 GVtoClusterMap.findLeader(
I.second);
208 MI != GVtoClusterMap.member_end(); ++
MI) {
209 if (!Visited.
insert(*MI).second)
212 << ((*MI)->hasLocalLinkage() ?
" l " :
" e ") <<
"\n");
214 ClusterIDMap[*
MI] = CurrentClusterID;
215 CurrentClusterSize++;
218 BalancingQueue.push(std::make_pair(CurrentClusterID, CurrentClusterSize));
231 GV->
setName(
"__llvmsplit_unnamed");
252 return (R[0] | (R[1] << 8)) %
N ==
I;
257 function_ref<
void(std::unique_ptr<Module> MPart)> ModuleCallback,
258 bool PreserveLocals,
bool RoundRobin) {
259 if (!PreserveLocals) {
272 ClusterIDMapType ClusterIDMap;
283 for (
const auto &
F : M.functions()) {
284 if (
F.isDeclaration() ||
285 F.getLinkage() != GlobalValue::LinkageTypes::ExternalLinkage)
287 auto It = ClusterIDMap.find(&
F);
288 if (It == ClusterIDMap.end())
291 ++ModuleFunctionCount[It->second];
293 BalancingQueueType BalancingQueue(compareClusters);
294 for (
unsigned I = 0;
I <
N; ++
I) {
295 if (
auto It = ModuleFunctionCount.
find(
I);
296 It != ModuleFunctionCount.
end())
297 BalancingQueue.push(*It);
299 BalancingQueue.push({
I, 0});
301 for (
const auto *
const F : UnmappedFunctions) {
302 const unsigned I = BalancingQueue.top().first;
303 const unsigned Count = BalancingQueue.top().second;
304 BalancingQueue.pop();
305 ClusterIDMap.insert({
F,
I});
306 BalancingQueue.push({
I, Count + 1});
313 for (
unsigned I = 0;
I <
N; ++
I) {
315 std::unique_ptr<Module> MPart(
317 if (
auto It = ClusterIDMap.find(GV); It != ClusterIDMap.end())
318 return It->second ==
I;
323 MPart->setModuleInlineAsm(
"");
324 ModuleCallback(std::move(MPart));
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file defines the DenseMap class.
Generic implementation of equivalence classes through the use Tarjan's efficient union-find algorithm...
Module.h This file contains the declarations for the Module class.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
static bool isInPartition(const GlobalValue *GV, unsigned I, unsigned N)
static void addNonConstUser(ClusterMapType &GVtoClusterMap, const GlobalValue *GV, const User *U)
static void findPartitions(Module &M, ClusterIDMapType &ClusterIDMap, unsigned N)
static void externalize(GlobalValue *GV)
static const GlobalObject * getGVPartitioningRoot(const GlobalValue *GV)
static void addAllGlobalValueUsers(ClusterMapType &GVtoClusterMap, const GlobalValue *GV, const Value *V)
LLVM Basic Block Representation.
The address of a basic block.
static BlockAddress * lookup(const BasicBlock *BB)
Lookup an existing BlockAddress constant for the given BasicBlock.
bool isConstantUsed() const
Return true if the constant has users other than constant expressions and other dangling things.
iterator find(const_arg_type_t< KeyT > Val)
EquivalenceClasses - This represents a collection of equivalence classes and supports three efficient...
bool hasLocalLinkage() const
const Comdat * getComdat() const
void setLinkage(LinkageTypes LT)
const GlobalObject * getAliaseeObject() const
@ HiddenVisibility
The GV is hidden.
void setVisibility(VisibilityTypes V)
@ ExternalLinkage
Externally visible function.
A Module instance is used to store all the information related to an LLVM module.
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 append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
LLVM Value Representation.
user_iterator user_begin()
void setName(const Twine &Name)
Change the name of the value.
StringRef getName() const
Return a constant reference to the value's name.
An efficient, type-erasing, non-owning reference to a callable.
This file contains the declaration of the Comdat class, which represents a single COMDAT in LLVM.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
This is an optimization pass for GlobalISel generic memory operations.
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
void SplitModule(Module &M, unsigned N, function_ref< void(std::unique_ptr< Module > MPart)> ModuleCallback, bool PreserveLocals=false, bool RoundRobin=false)
Splits the module M into N linkable partitions.
void sort(IteratorTy Start, IteratorTy End)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
std::unique_ptr< Module > CloneModule(const Module &M)
Return an exact copy of the specified module.