1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-22 20:43:44 +02:00
llvm-mirror/lib/Transforms/Utils/SplitModule.cpp
Peter Collingbourne 96b0ffdce8 TransformUtils: Introduce module splitter.
The module splitter splits a module into linkable partitions. It will
be used to implement parallel LTO code generation.

This initial version of the splitter does not attempt to deal with the
somewhat subtle symbol visibility issues around module splitting. These
will be dealt with in a future change.

Differential Revision: http://reviews.llvm.org/D12132

llvm-svn: 245662
2015-08-21 02:48:20 +00:00

86 lines
2.7 KiB
C++

//===- SplitModule.cpp - Split a module into partitions -------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the function llvm::SplitModule, which splits a module
// into multiple linkable partitions. It can be used to implement parallel code
// generation for link-time optimization.
//
//===----------------------------------------------------------------------===//
#include "llvm/Transforms/Utils/SplitModule.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalAlias.h"
#include "llvm/IR/GlobalObject.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/MD5.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Utils/Cloning.h"
using namespace llvm;
static void externalize(GlobalValue *GV) {
if (GV->hasLocalLinkage()) {
GV->setLinkage(GlobalValue::ExternalLinkage);
GV->setVisibility(GlobalValue::HiddenVisibility);
}
// Unnamed entities must be named consistently between modules. setName will
// give a distinct name to each such entity.
if (!GV->hasName())
GV->setName("__llvmsplit_unnamed");
}
// Returns whether GV should be in partition (0-based) I of N.
static bool isInPartition(const GlobalValue *GV, unsigned I, unsigned N) {
if (auto GA = dyn_cast<GlobalAlias>(GV))
if (const GlobalObject *Base = GA->getBaseObject())
GV = Base;
StringRef Name;
if (const Comdat *C = GV->getComdat())
Name = C->getName();
else
Name = GV->getName();
// Partition by MD5 hash. We only need a few bits for evenness as the number
// of partitions will generally be in the 1-2 figure range; the low 16 bits
// are enough.
MD5 H;
MD5::MD5Result R;
H.update(Name);
H.final(R);
return (R[0] | (R[1] << 8)) % N == I;
}
void llvm::SplitModule(
std::unique_ptr<Module> M, unsigned N,
std::function<void(std::unique_ptr<Module> MPart)> ModuleCallback) {
for (Function &F : *M)
externalize(&F);
for (GlobalVariable &GV : M->globals())
externalize(&GV);
for (GlobalAlias &GA : M->aliases())
externalize(&GA);
// FIXME: We should be able to reuse M as the last partition instead of
// cloning it.
for (unsigned I = 0; I != N; ++I) {
ValueToValueMapTy VMap;
std::unique_ptr<Module> MPart(
CloneModule(M.get(), VMap, [=](const GlobalValue *GV) {
return isInPartition(GV, I, N);
}));
if (I != 0)
MPart->setModuleInlineAsm("");
ModuleCallback(std::move(MPart));
}
}