mirror of
https://github.com/RPCS3/llvm.git
synced 2025-02-21 03:00:45 +00:00
Fix a performance bug in the Linker.
Now that we hava a convinient place to keep it, remeber the set of identified structs as we merge modules. This speeds up the linking of all the bitcode files in clang with the gold plugin and -plugin-opt=emit-llvm (i.e., link only, no codegen) from 5:25 minutes to 13.6 seconds! Patch by Xiaofei Wan! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@181104 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
2e013028f2
commit
cfb320f5f9
@ -10,12 +10,14 @@
|
||||
#ifndef LLVM_LINKER_H
|
||||
#define LLVM_LINKER_H
|
||||
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include <string>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class Module;
|
||||
class StringRef;
|
||||
class StructType;
|
||||
|
||||
/// This class provides the core functionality of linking in LLVM. It keeps a
|
||||
/// pointer to the merged module so far. It doesn't take ownership of the
|
||||
@ -47,6 +49,7 @@ class Linker {
|
||||
|
||||
private:
|
||||
Module *Composite;
|
||||
SmallPtrSet<StructType*, 32> IdentifiedStructTypes;
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
@ -29,6 +29,8 @@ using namespace llvm;
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
namespace {
|
||||
typedef SmallPtrSet<StructType*, 32> TypeSet;
|
||||
|
||||
class TypeMapTy : public ValueMapTypeRemapper {
|
||||
/// MappedTypes - This is a mapping from a source type to a destination type
|
||||
/// to use.
|
||||
@ -49,6 +51,9 @@ class TypeMapTy : public ValueMapTypeRemapper {
|
||||
SmallPtrSet<StructType*, 16> DstResolvedOpaqueTypes;
|
||||
|
||||
public:
|
||||
TypeMapTy(TypeSet &Set) : DstStructTypesSet(Set) {}
|
||||
|
||||
TypeSet &DstStructTypesSet;
|
||||
/// addTypeMapping - Indicate that the specified type in the destination
|
||||
/// module is conceptually equivalent to the specified type in the source
|
||||
/// module.
|
||||
@ -325,13 +330,20 @@ Type *TypeMapTy::getImpl(Type *Ty) {
|
||||
StructType *STy = cast<StructType>(Ty);
|
||||
|
||||
// If the type is opaque, we can just use it directly.
|
||||
if (STy->isOpaque())
|
||||
if (STy->isOpaque()) {
|
||||
// A named structure type from src module is used. Add it to the Set of
|
||||
// identified structs in the destination module.
|
||||
DstStructTypesSet.insert(STy);
|
||||
return *Entry = STy;
|
||||
}
|
||||
|
||||
// Otherwise we create a new type and resolve its body later. This will be
|
||||
// resolved by the top level of get().
|
||||
SrcDefinitionsToResolve.push_back(STy);
|
||||
StructType *DTy = StructType::create(STy->getContext());
|
||||
// A new identified structure type was created. Add it to the set of
|
||||
// identified structs in the destination module.
|
||||
DstStructTypesSet.insert(DTy);
|
||||
DstResolvedOpaqueTypes.insert(DTy);
|
||||
return *Entry = DTy;
|
||||
}
|
||||
@ -373,8 +385,8 @@ namespace {
|
||||
public:
|
||||
std::string ErrorMsg;
|
||||
|
||||
ModuleLinker(Module *dstM, Module *srcM, unsigned mode)
|
||||
: DstM(dstM), SrcM(srcM), Mode(mode) { }
|
||||
ModuleLinker(Module *dstM, TypeSet &Set, Module *srcM, unsigned mode)
|
||||
: DstM(dstM), SrcM(srcM), TypeMap(Set), Mode(mode) { }
|
||||
|
||||
bool run();
|
||||
|
||||
@ -588,11 +600,6 @@ void ModuleLinker::computeTypeMapping() {
|
||||
SmallPtrSet<StructType*, 32> SrcStructTypesSet(SrcStructTypes.begin(),
|
||||
SrcStructTypes.end());
|
||||
|
||||
TypeFinder DstStructTypes;
|
||||
DstStructTypes.run(*DstM, true);
|
||||
SmallPtrSet<StructType*, 32> DstStructTypesSet(DstStructTypes.begin(),
|
||||
DstStructTypes.end());
|
||||
|
||||
for (unsigned i = 0, e = SrcStructTypes.size(); i != e; ++i) {
|
||||
StructType *ST = SrcStructTypes[i];
|
||||
if (!ST->hasName()) continue;
|
||||
@ -623,7 +630,7 @@ void ModuleLinker::computeTypeMapping() {
|
||||
// we prefer to take the '%C' version. So we are then left with both
|
||||
// '%C.1' and '%C' being used for the same types. This leads to some
|
||||
// variables using one type and some using the other.
|
||||
if (!SrcStructTypesSet.count(DST) && DstStructTypesSet.count(DST))
|
||||
if (!SrcStructTypesSet.count(DST) && TypeMap.DstStructTypesSet.count(DST))
|
||||
TypeMap.addTypeMapping(DST, ST);
|
||||
}
|
||||
|
||||
@ -1281,13 +1288,17 @@ bool ModuleLinker::run() {
|
||||
return false;
|
||||
}
|
||||
|
||||
Linker::Linker(Module *M) : Composite(M) {}
|
||||
Linker::Linker(Module *M) : Composite(M) {
|
||||
TypeFinder StructTypes;
|
||||
StructTypes.run(*M, true);
|
||||
IdentifiedStructTypes.insert(StructTypes.begin(), StructTypes.end());
|
||||
}
|
||||
|
||||
Linker::~Linker() {
|
||||
}
|
||||
|
||||
bool Linker::linkInModule(Module *Src, unsigned Mode, std::string *ErrorMsg) {
|
||||
ModuleLinker TheLinker(Composite, Src, Mode);
|
||||
ModuleLinker TheLinker(Composite, IdentifiedStructTypes, Src, Mode);
|
||||
if (TheLinker.run()) {
|
||||
if (ErrorMsg)
|
||||
*ErrorMsg = TheLinker.ErrorMsg;
|
||||
|
Loading…
x
Reference in New Issue
Block a user