10b57cec5SDimitry Andric //===- SplitModule.cpp - Split a module into partitions -------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file defines the function llvm::SplitModule, which splits a module 100b57cec5SDimitry Andric // into multiple linkable partitions. It can be used to implement parallel code 110b57cec5SDimitry Andric // generation for link-time optimization. 120b57cec5SDimitry Andric // 130b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 140b57cec5SDimitry Andric 150b57cec5SDimitry Andric #include "llvm/Transforms/Utils/SplitModule.h" 160b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h" 170b57cec5SDimitry Andric #include "llvm/ADT/EquivalenceClasses.h" 180b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h" 190b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 200b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 210b57cec5SDimitry Andric #include "llvm/IR/Comdat.h" 220b57cec5SDimitry Andric #include "llvm/IR/Constant.h" 230b57cec5SDimitry Andric #include "llvm/IR/Constants.h" 240b57cec5SDimitry Andric #include "llvm/IR/Function.h" 250b57cec5SDimitry Andric #include "llvm/IR/GlobalAlias.h" 260b57cec5SDimitry Andric #include "llvm/IR/GlobalObject.h" 270b57cec5SDimitry Andric #include "llvm/IR/GlobalValue.h" 280b57cec5SDimitry Andric #include "llvm/IR/GlobalVariable.h" 290b57cec5SDimitry Andric #include "llvm/IR/Instruction.h" 300b57cec5SDimitry Andric #include "llvm/IR/Module.h" 310b57cec5SDimitry Andric #include "llvm/IR/User.h" 320b57cec5SDimitry Andric #include "llvm/IR/Value.h" 330b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 340b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 350b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 360b57cec5SDimitry Andric #include "llvm/Support/MD5.h" 370b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 380b57cec5SDimitry Andric #include "llvm/Transforms/Utils/Cloning.h" 390b57cec5SDimitry Andric #include "llvm/Transforms/Utils/ValueMapper.h" 400b57cec5SDimitry Andric #include <algorithm> 410b57cec5SDimitry Andric #include <cassert> 420b57cec5SDimitry Andric #include <iterator> 430b57cec5SDimitry Andric #include <memory> 440b57cec5SDimitry Andric #include <queue> 450b57cec5SDimitry Andric #include <utility> 460b57cec5SDimitry Andric #include <vector> 470b57cec5SDimitry Andric 480b57cec5SDimitry Andric using namespace llvm; 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric #define DEBUG_TYPE "split-module" 510b57cec5SDimitry Andric 520b57cec5SDimitry Andric namespace { 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric using ClusterMapType = EquivalenceClasses<const GlobalValue *>; 550b57cec5SDimitry Andric using ComdatMembersType = DenseMap<const Comdat *, const GlobalValue *>; 560b57cec5SDimitry Andric using ClusterIDMapType = DenseMap<const GlobalValue *, unsigned>; 570b57cec5SDimitry Andric 58*0fca6ea1SDimitry Andric bool compareClusters(const std::pair<unsigned, unsigned> &A, 59*0fca6ea1SDimitry Andric const std::pair<unsigned, unsigned> &B) { 60*0fca6ea1SDimitry Andric if (A.second || B.second) 61*0fca6ea1SDimitry Andric return A.second > B.second; 62*0fca6ea1SDimitry Andric return A.first > B.first; 63*0fca6ea1SDimitry Andric } 64*0fca6ea1SDimitry Andric 65*0fca6ea1SDimitry Andric using BalancingQueueType = 66*0fca6ea1SDimitry Andric std::priority_queue<std::pair<unsigned, unsigned>, 67*0fca6ea1SDimitry Andric std::vector<std::pair<unsigned, unsigned>>, 68*0fca6ea1SDimitry Andric decltype(compareClusters) *>; 69*0fca6ea1SDimitry Andric 700b57cec5SDimitry Andric } // end anonymous namespace 710b57cec5SDimitry Andric 720b57cec5SDimitry Andric static void addNonConstUser(ClusterMapType &GVtoClusterMap, 730b57cec5SDimitry Andric const GlobalValue *GV, const User *U) { 740b57cec5SDimitry Andric assert((!isa<Constant>(U) || isa<GlobalValue>(U)) && "Bad user"); 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric if (const Instruction *I = dyn_cast<Instruction>(U)) { 770b57cec5SDimitry Andric const GlobalValue *F = I->getParent()->getParent(); 780b57cec5SDimitry Andric GVtoClusterMap.unionSets(GV, F); 79349cc55cSDimitry Andric } else if (const GlobalValue *GVU = dyn_cast<GlobalValue>(U)) { 80349cc55cSDimitry Andric GVtoClusterMap.unionSets(GV, GVU); 810b57cec5SDimitry Andric } else { 820b57cec5SDimitry Andric llvm_unreachable("Underimplemented use case"); 830b57cec5SDimitry Andric } 840b57cec5SDimitry Andric } 850b57cec5SDimitry Andric 860b57cec5SDimitry Andric // Adds all GlobalValue users of V to the same cluster as GV. 870b57cec5SDimitry Andric static void addAllGlobalValueUsers(ClusterMapType &GVtoClusterMap, 880b57cec5SDimitry Andric const GlobalValue *GV, const Value *V) { 89bdd1243dSDimitry Andric for (const auto *U : V->users()) { 900b57cec5SDimitry Andric SmallVector<const User *, 4> Worklist; 910b57cec5SDimitry Andric Worklist.push_back(U); 920b57cec5SDimitry Andric while (!Worklist.empty()) { 930b57cec5SDimitry Andric const User *UU = Worklist.pop_back_val(); 940b57cec5SDimitry Andric // For each constant that is not a GV (a pure const) recurse. 950b57cec5SDimitry Andric if (isa<Constant>(UU) && !isa<GlobalValue>(UU)) { 960b57cec5SDimitry Andric Worklist.append(UU->user_begin(), UU->user_end()); 970b57cec5SDimitry Andric continue; 980b57cec5SDimitry Andric } 990b57cec5SDimitry Andric addNonConstUser(GVtoClusterMap, GV, UU); 1000b57cec5SDimitry Andric } 1010b57cec5SDimitry Andric } 1020b57cec5SDimitry Andric } 1030b57cec5SDimitry Andric 104349cc55cSDimitry Andric static const GlobalObject *getGVPartitioningRoot(const GlobalValue *GV) { 105349cc55cSDimitry Andric const GlobalObject *GO = GV->getAliaseeObject(); 106349cc55cSDimitry Andric if (const auto *GI = dyn_cast_or_null<GlobalIFunc>(GO)) 107349cc55cSDimitry Andric GO = GI->getResolverFunction(); 108349cc55cSDimitry Andric return GO; 109349cc55cSDimitry Andric } 110349cc55cSDimitry Andric 1110b57cec5SDimitry Andric // Find partitions for module in the way that no locals need to be 1120b57cec5SDimitry Andric // globalized. 1130b57cec5SDimitry Andric // Try to balance pack those partitions into N files since this roughly equals 1140b57cec5SDimitry Andric // thread balancing for the backend codegen step. 115fe6060f1SDimitry Andric static void findPartitions(Module &M, ClusterIDMapType &ClusterIDMap, 1160b57cec5SDimitry Andric unsigned N) { 1170b57cec5SDimitry Andric // At this point module should have the proper mix of globals and locals. 1180b57cec5SDimitry Andric // As we attempt to partition this module, we must not change any 1190b57cec5SDimitry Andric // locals to globals. 120*0fca6ea1SDimitry Andric LLVM_DEBUG(dbgs() << "Partition module with (" << M.size() 121*0fca6ea1SDimitry Andric << ") functions\n"); 1220b57cec5SDimitry Andric ClusterMapType GVtoClusterMap; 1230b57cec5SDimitry Andric ComdatMembersType ComdatMembers; 1240b57cec5SDimitry Andric 1250b57cec5SDimitry Andric auto recordGVSet = [&GVtoClusterMap, &ComdatMembers](GlobalValue &GV) { 1260b57cec5SDimitry Andric if (GV.isDeclaration()) 1270b57cec5SDimitry Andric return; 1280b57cec5SDimitry Andric 1290b57cec5SDimitry Andric if (!GV.hasName()) 1300b57cec5SDimitry Andric GV.setName("__llvmsplit_unnamed"); 1310b57cec5SDimitry Andric 1320b57cec5SDimitry Andric // Comdat groups must not be partitioned. For comdat groups that contain 1330b57cec5SDimitry Andric // locals, record all their members here so we can keep them together. 1340b57cec5SDimitry Andric // Comdat groups that only contain external globals are already handled by 1350b57cec5SDimitry Andric // the MD5-based partitioning. 1360b57cec5SDimitry Andric if (const Comdat *C = GV.getComdat()) { 1370b57cec5SDimitry Andric auto &Member = ComdatMembers[C]; 1380b57cec5SDimitry Andric if (Member) 1390b57cec5SDimitry Andric GVtoClusterMap.unionSets(Member, &GV); 1400b57cec5SDimitry Andric else 1410b57cec5SDimitry Andric Member = &GV; 1420b57cec5SDimitry Andric } 1430b57cec5SDimitry Andric 144349cc55cSDimitry Andric // Aliases should not be separated from their aliasees and ifuncs should 145349cc55cSDimitry Andric // not be separated from their resolvers regardless of linkage. 146349cc55cSDimitry Andric if (const GlobalObject *Root = getGVPartitioningRoot(&GV)) 147349cc55cSDimitry Andric if (&GV != Root) 148349cc55cSDimitry Andric GVtoClusterMap.unionSets(&GV, Root); 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric if (const Function *F = dyn_cast<Function>(&GV)) { 1510b57cec5SDimitry Andric for (const BasicBlock &BB : *F) { 1520b57cec5SDimitry Andric BlockAddress *BA = BlockAddress::lookup(&BB); 1530b57cec5SDimitry Andric if (!BA || !BA->isConstantUsed()) 1540b57cec5SDimitry Andric continue; 1550b57cec5SDimitry Andric addAllGlobalValueUsers(GVtoClusterMap, F, BA); 1560b57cec5SDimitry Andric } 1570b57cec5SDimitry Andric } 1580b57cec5SDimitry Andric 1590b57cec5SDimitry Andric if (GV.hasLocalLinkage()) 1600b57cec5SDimitry Andric addAllGlobalValueUsers(GVtoClusterMap, &GV, &GV); 1610b57cec5SDimitry Andric }; 1620b57cec5SDimitry Andric 163fe6060f1SDimitry Andric llvm::for_each(M.functions(), recordGVSet); 164fe6060f1SDimitry Andric llvm::for_each(M.globals(), recordGVSet); 165fe6060f1SDimitry Andric llvm::for_each(M.aliases(), recordGVSet); 1660b57cec5SDimitry Andric 1670b57cec5SDimitry Andric // Assigned all GVs to merged clusters while balancing number of objects in 1680b57cec5SDimitry Andric // each. 169*0fca6ea1SDimitry Andric BalancingQueueType BalancingQueue(compareClusters); 1700b57cec5SDimitry Andric // Pre-populate priority queue with N slot blanks. 1710b57cec5SDimitry Andric for (unsigned i = 0; i < N; ++i) 172*0fca6ea1SDimitry Andric BalancingQueue.push(std::make_pair(i, 0)); 1730b57cec5SDimitry Andric 1740b57cec5SDimitry Andric using SortType = std::pair<unsigned, ClusterMapType::iterator>; 1750b57cec5SDimitry Andric 1760b57cec5SDimitry Andric SmallVector<SortType, 64> Sets; 1770b57cec5SDimitry Andric SmallPtrSet<const GlobalValue *, 32> Visited; 1780b57cec5SDimitry Andric 1790b57cec5SDimitry Andric // To guarantee determinism, we have to sort SCC according to size. 1800b57cec5SDimitry Andric // When size is the same, use leader's name. 1810b57cec5SDimitry Andric for (ClusterMapType::iterator I = GVtoClusterMap.begin(), 182*0fca6ea1SDimitry Andric E = GVtoClusterMap.end(); 183*0fca6ea1SDimitry Andric I != E; ++I) 1840b57cec5SDimitry Andric if (I->isLeader()) 1850b57cec5SDimitry Andric Sets.push_back( 1860b57cec5SDimitry Andric std::make_pair(std::distance(GVtoClusterMap.member_begin(I), 187*0fca6ea1SDimitry Andric GVtoClusterMap.member_end()), 188*0fca6ea1SDimitry Andric I)); 1890b57cec5SDimitry Andric 1900b57cec5SDimitry Andric llvm::sort(Sets, [](const SortType &a, const SortType &b) { 1910b57cec5SDimitry Andric if (a.first == b.first) 1920b57cec5SDimitry Andric return a.second->getData()->getName() > b.second->getData()->getName(); 1930b57cec5SDimitry Andric else 1940b57cec5SDimitry Andric return a.first > b.first; 1950b57cec5SDimitry Andric }); 1960b57cec5SDimitry Andric 1970b57cec5SDimitry Andric for (auto &I : Sets) { 198*0fca6ea1SDimitry Andric unsigned CurrentClusterID = BalancingQueue.top().first; 199*0fca6ea1SDimitry Andric unsigned CurrentClusterSize = BalancingQueue.top().second; 200*0fca6ea1SDimitry Andric BalancingQueue.pop(); 2010b57cec5SDimitry Andric 2020b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "Root[" << CurrentClusterID << "] cluster_size(" 2030b57cec5SDimitry Andric << I.first << ") ----> " << I.second->getData()->getName() 2040b57cec5SDimitry Andric << "\n"); 2050b57cec5SDimitry Andric 2060b57cec5SDimitry Andric for (ClusterMapType::member_iterator MI = 2070b57cec5SDimitry Andric GVtoClusterMap.findLeader(I.second); 2080b57cec5SDimitry Andric MI != GVtoClusterMap.member_end(); ++MI) { 2090b57cec5SDimitry Andric if (!Visited.insert(*MI).second) 2100b57cec5SDimitry Andric continue; 2110b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "----> " << (*MI)->getName() 2120b57cec5SDimitry Andric << ((*MI)->hasLocalLinkage() ? " l " : " e ") << "\n"); 2130b57cec5SDimitry Andric Visited.insert(*MI); 2140b57cec5SDimitry Andric ClusterIDMap[*MI] = CurrentClusterID; 2150b57cec5SDimitry Andric CurrentClusterSize++; 2160b57cec5SDimitry Andric } 2170b57cec5SDimitry Andric // Add this set size to the number of entries in this cluster. 218*0fca6ea1SDimitry Andric BalancingQueue.push(std::make_pair(CurrentClusterID, CurrentClusterSize)); 2190b57cec5SDimitry Andric } 2200b57cec5SDimitry Andric } 2210b57cec5SDimitry Andric 2220b57cec5SDimitry Andric static void externalize(GlobalValue *GV) { 2230b57cec5SDimitry Andric if (GV->hasLocalLinkage()) { 2240b57cec5SDimitry Andric GV->setLinkage(GlobalValue::ExternalLinkage); 2250b57cec5SDimitry Andric GV->setVisibility(GlobalValue::HiddenVisibility); 2260b57cec5SDimitry Andric } 2270b57cec5SDimitry Andric 2280b57cec5SDimitry Andric // Unnamed entities must be named consistently between modules. setName will 2290b57cec5SDimitry Andric // give a distinct name to each such entity. 2300b57cec5SDimitry Andric if (!GV->hasName()) 2310b57cec5SDimitry Andric GV->setName("__llvmsplit_unnamed"); 2320b57cec5SDimitry Andric } 2330b57cec5SDimitry Andric 2340b57cec5SDimitry Andric // Returns whether GV should be in partition (0-based) I of N. 2350b57cec5SDimitry Andric static bool isInPartition(const GlobalValue *GV, unsigned I, unsigned N) { 236349cc55cSDimitry Andric if (const GlobalObject *Root = getGVPartitioningRoot(GV)) 237349cc55cSDimitry Andric GV = Root; 2380b57cec5SDimitry Andric 2390b57cec5SDimitry Andric StringRef Name; 2400b57cec5SDimitry Andric if (const Comdat *C = GV->getComdat()) 2410b57cec5SDimitry Andric Name = C->getName(); 2420b57cec5SDimitry Andric else 2430b57cec5SDimitry Andric Name = GV->getName(); 2440b57cec5SDimitry Andric 2450b57cec5SDimitry Andric // Partition by MD5 hash. We only need a few bits for evenness as the number 2460b57cec5SDimitry Andric // of partitions will generally be in the 1-2 figure range; the low 16 bits 2470b57cec5SDimitry Andric // are enough. 2480b57cec5SDimitry Andric MD5 H; 2490b57cec5SDimitry Andric MD5::MD5Result R; 2500b57cec5SDimitry Andric H.update(Name); 2510b57cec5SDimitry Andric H.final(R); 2520b57cec5SDimitry Andric return (R[0] | (R[1] << 8)) % N == I; 2530b57cec5SDimitry Andric } 2540b57cec5SDimitry Andric 2550b57cec5SDimitry Andric void llvm::SplitModule( 256fe6060f1SDimitry Andric Module &M, unsigned N, 2570b57cec5SDimitry Andric function_ref<void(std::unique_ptr<Module> MPart)> ModuleCallback, 258*0fca6ea1SDimitry Andric bool PreserveLocals, bool RoundRobin) { 2590b57cec5SDimitry Andric if (!PreserveLocals) { 260fe6060f1SDimitry Andric for (Function &F : M) 2610b57cec5SDimitry Andric externalize(&F); 262fe6060f1SDimitry Andric for (GlobalVariable &GV : M.globals()) 2630b57cec5SDimitry Andric externalize(&GV); 264fe6060f1SDimitry Andric for (GlobalAlias &GA : M.aliases()) 2650b57cec5SDimitry Andric externalize(&GA); 266fe6060f1SDimitry Andric for (GlobalIFunc &GIF : M.ifuncs()) 2670b57cec5SDimitry Andric externalize(&GIF); 2680b57cec5SDimitry Andric } 2690b57cec5SDimitry Andric 2700b57cec5SDimitry Andric // This performs splitting without a need for externalization, which might not 2710b57cec5SDimitry Andric // always be possible. 2720b57cec5SDimitry Andric ClusterIDMapType ClusterIDMap; 273fe6060f1SDimitry Andric findPartitions(M, ClusterIDMap, N); 2740b57cec5SDimitry Andric 275*0fca6ea1SDimitry Andric // Find functions not mapped to modules in ClusterIDMap and count functions 276*0fca6ea1SDimitry Andric // per module. Map unmapped functions using round-robin so that they skip 277*0fca6ea1SDimitry Andric // being distributed by isInPartition() based on function name hashes below. 278*0fca6ea1SDimitry Andric // This provides better uniformity of distribution of functions to modules 279*0fca6ea1SDimitry Andric // in some cases - for example when the number of functions equals to N. 280*0fca6ea1SDimitry Andric if (RoundRobin) { 281*0fca6ea1SDimitry Andric DenseMap<unsigned, unsigned> ModuleFunctionCount; 282*0fca6ea1SDimitry Andric SmallVector<const GlobalValue *> UnmappedFunctions; 283*0fca6ea1SDimitry Andric for (const auto &F : M.functions()) { 284*0fca6ea1SDimitry Andric if (F.isDeclaration() || 285*0fca6ea1SDimitry Andric F.getLinkage() != GlobalValue::LinkageTypes::ExternalLinkage) 286*0fca6ea1SDimitry Andric continue; 287*0fca6ea1SDimitry Andric auto It = ClusterIDMap.find(&F); 288*0fca6ea1SDimitry Andric if (It == ClusterIDMap.end()) 289*0fca6ea1SDimitry Andric UnmappedFunctions.push_back(&F); 290*0fca6ea1SDimitry Andric else 291*0fca6ea1SDimitry Andric ++ModuleFunctionCount[It->second]; 292*0fca6ea1SDimitry Andric } 293*0fca6ea1SDimitry Andric BalancingQueueType BalancingQueue(compareClusters); 294*0fca6ea1SDimitry Andric for (unsigned I = 0; I < N; ++I) { 295*0fca6ea1SDimitry Andric if (auto It = ModuleFunctionCount.find(I); 296*0fca6ea1SDimitry Andric It != ModuleFunctionCount.end()) 297*0fca6ea1SDimitry Andric BalancingQueue.push(*It); 298*0fca6ea1SDimitry Andric else 299*0fca6ea1SDimitry Andric BalancingQueue.push({I, 0}); 300*0fca6ea1SDimitry Andric } 301*0fca6ea1SDimitry Andric for (const auto *const F : UnmappedFunctions) { 302*0fca6ea1SDimitry Andric const unsigned I = BalancingQueue.top().first; 303*0fca6ea1SDimitry Andric const unsigned Count = BalancingQueue.top().second; 304*0fca6ea1SDimitry Andric BalancingQueue.pop(); 305*0fca6ea1SDimitry Andric ClusterIDMap.insert({F, I}); 306*0fca6ea1SDimitry Andric BalancingQueue.push({I, Count + 1}); 307*0fca6ea1SDimitry Andric } 308*0fca6ea1SDimitry Andric } 309*0fca6ea1SDimitry Andric 3100b57cec5SDimitry Andric // FIXME: We should be able to reuse M as the last partition instead of 311fe6060f1SDimitry Andric // cloning it. Note that the callers at the moment expect the module to 312fe6060f1SDimitry Andric // be preserved, so will need some adjustments as well. 3130b57cec5SDimitry Andric for (unsigned I = 0; I < N; ++I) { 3140b57cec5SDimitry Andric ValueToValueMapTy VMap; 3150b57cec5SDimitry Andric std::unique_ptr<Module> MPart( 316fe6060f1SDimitry Andric CloneModule(M, VMap, [&](const GlobalValue *GV) { 317*0fca6ea1SDimitry Andric if (auto It = ClusterIDMap.find(GV); It != ClusterIDMap.end()) 318*0fca6ea1SDimitry Andric return It->second == I; 3190b57cec5SDimitry Andric else 3200b57cec5SDimitry Andric return isInPartition(GV, I, N); 3210b57cec5SDimitry Andric })); 3220b57cec5SDimitry Andric if (I != 0) 3230b57cec5SDimitry Andric MPart->setModuleInlineAsm(""); 3240b57cec5SDimitry Andric ModuleCallback(std::move(MPart)); 3250b57cec5SDimitry Andric } 3260b57cec5SDimitry Andric } 327