Index: include/llvm/IR/GlobalValue.h =================================================================== --- include/llvm/IR/GlobalValue.h +++ include/llvm/IR/GlobalValue.h @@ -273,6 +273,7 @@ PointerType *getType() const { return cast(User::getType()); } Type *getValueType() const { return ValueType; } + void mutateValueType(Type *Ty) { ValueType = Ty; } void setDSOLocal(bool Local) { IsDSOLocal = Local; } Index: include/llvm/IR/TypeFinder.h =================================================================== --- include/llvm/IR/TypeFinder.h +++ include/llvm/IR/TypeFinder.h @@ -62,19 +62,9 @@ DenseSet &getVisitedMetadata() { return VisitedMetadata; } private: - /// incorporateType - This method adds the type to the list of used - /// structures if it's not in there already. + /// This method adds the type to the list of used structures if it's not in + /// there already. void incorporateType(Type *Ty); - - /// incorporateValue - This method is used to walk operand lists finding types - /// hiding in constant expressions and other operands that won't be walked in - /// other ways. GlobalValues, basic blocks, instructions, and inst operands - /// are all explicitly enumerated. - void incorporateValue(const Value *V); - - /// incorporateMDNode - This method is used to walk the operands of an MDNode - /// to find types hiding within. - void incorporateMDNode(const MDNode *V); }; } // end namespace llvm Index: include/llvm/IR/ValueVisitor.h =================================================================== --- /dev/null +++ include/llvm/IR/ValueVisitor.h @@ -0,0 +1,16 @@ +#ifndef LLVM_IR_VALUEVISITOR_H +#define LLVM_IR_VALUEVISITOR_H + +#include + +namespace llvm { +class Module; +class MDNode; +class Value; + +void visitAllValues(Module &M, std::function Visit); +void visitAllValues(const Module &M, std::function Visit); + +} // namespace llvm + +#endif Index: lib/IR/CMakeLists.txt =================================================================== --- lib/IR/CMakeLists.txt +++ lib/IR/CMakeLists.txt @@ -53,6 +53,7 @@ Value.cpp ValueSymbolTable.cpp ValueTypes.cpp + ValueVisitor.cpp Verifier.cpp ADDITIONAL_HEADER_DIRS Index: lib/IR/TypeFinder.cpp =================================================================== --- lib/IR/TypeFinder.cpp +++ lib/IR/TypeFinder.cpp @@ -24,6 +24,7 @@ #include "llvm/IR/Use.h" #include "llvm/IR/User.h" #include "llvm/IR/Value.h" +#include "llvm/IR/ValueVisitor.h" #include "llvm/Support/Casting.h" #include @@ -31,55 +32,7 @@ void TypeFinder::run(const Module &M, bool onlyNamed) { OnlyNamed = onlyNamed; - - // Get types from global variables. - for (const auto &G : M.globals()) { - incorporateType(G.getType()); - if (G.hasInitializer()) - incorporateValue(G.getInitializer()); - } - - // Get types from aliases. - for (const auto &A : M.aliases()) { - incorporateType(A.getType()); - if (const Value *Aliasee = A.getAliasee()) - incorporateValue(Aliasee); - } - - // Get types from functions. - SmallVector, 4> MDForInst; - for (const Function &FI : M) { - incorporateType(FI.getType()); - - for (const Use &U : FI.operands()) - incorporateValue(U.get()); - - // First incorporate the arguments. - for (const auto &A : FI.args()) - incorporateValue(&A); - - for (const BasicBlock &BB : FI) - for (const Instruction &I : BB) { - // Incorporate the type of the instruction. - incorporateType(I.getType()); - - // Incorporate non-instruction operand types. (We are incorporating all - // instructions with this loop.) - for (const auto &O : I.operands()) - if (&*O && !isa(&*O)) - incorporateValue(&*O); - - // Incorporate types hiding in metadata. - I.getAllMetadataOtherThanDebugLoc(MDForInst); - for (const auto &MD : MDForInst) - incorporateMDNode(MD.second); - MDForInst.clear(); - } - } - - for (const auto &NMD : M.named_metadata()) - for (const auto &MDOp : NMD.operands()) - incorporateMDNode(MDOp); + visitAllValues(M, [&](const Value &V) { incorporateType(V.getType()); }); } void TypeFinder::clear() { @@ -88,8 +41,8 @@ StructTypes.clear(); } -/// incorporateType - This method adds the type to the list of used structures -/// if it's not in there already. +/// This method adds the type to the list of used structures if it's not in +/// there already. void TypeFinder::incorporateType(Type *Ty) { // Check to see if we've already visited this type. if (!VisitedTypes.insert(Ty).second) @@ -113,57 +66,3 @@ TypeWorklist.push_back(*I); } while (!TypeWorklist.empty()); } - -/// incorporateValue - This method is used to walk operand lists finding types -/// hiding in constant expressions and other operands that won't be walked in -/// other ways. GlobalValues, basic blocks, instructions, and inst operands are -/// all explicitly enumerated. -void TypeFinder::incorporateValue(const Value *V) { - if (const auto *M = dyn_cast(V)) { - if (const auto *N = dyn_cast(M->getMetadata())) - return incorporateMDNode(N); - if (const auto *MDV = dyn_cast(M->getMetadata())) - return incorporateValue(MDV->getValue()); - return; - } - - if (!isa(V) || isa(V)) return; - - // Already visited? - if (!VisitedConstants.insert(V).second) - return; - - // Check this type. - incorporateType(V->getType()); - - // If this is an instruction, we incorporate it separately. - if (isa(V)) - return; - - // Look in operands for types. - const User *U = cast(V); - for (const auto &I : U->operands()) - incorporateValue(&*I); -} - -/// incorporateMDNode - This method is used to walk the operands of an MDNode to -/// find types hiding within. -void TypeFinder::incorporateMDNode(const MDNode *V) { - // Already visited? - if (!VisitedMetadata.insert(V).second) - return; - - // Look in operands for types. - for (Metadata *Op : V->operands()) { - if (!Op) - continue; - if (auto *N = dyn_cast(Op)) { - incorporateMDNode(N); - continue; - } - if (auto *C = dyn_cast(Op)) { - incorporateValue(C->getValue()); - continue; - } - } -} Index: lib/IR/ValueVisitor.cpp =================================================================== --- /dev/null +++ lib/IR/ValueVisitor.cpp @@ -0,0 +1,116 @@ +#include "llvm/IR/ValueVisitor.h" +#include "llvm/IR/Module.h" + +using namespace llvm; + +namespace { +class ValueVisitor { + DenseSet Visited; + DenseSet VisitedMDNode; + Module &M; + std::function Visit; + void visitValue(Value &V); + void visitMDNode(MDNode &MD); + void visitMetadata(Metadata &MD); + +public: + ValueVisitor(Module &M, std::function Visit) + : M(M), Visit(Visit) {} + void run(); +}; +} // namespace + +void ValueVisitor::visitValue(Value &V) { + if (!Visited.insert(&V).second) + return; + + Visit(V); + + if (isa(V) || isa(V)) + return; + + if (auto *GV = dyn_cast(&V)) { + if (GV->hasInitializer()) + visitValue(*GV->getInitializer()); + return; + } + + if (auto *GIS = dyn_cast(&V)) { + if (auto *Ind = GIS->getIndirectSymbol()) + visitValue(*Ind); + return; + } + + if (auto *BB = dyn_cast(&V)) { + for (Instruction &I : *BB) + visitValue(I); + return; + } + + if (auto *I = dyn_cast(&V)) { + for (auto &O : I->operands()) + visitValue(*O); + SmallVector, 4> MDForInst; + I->getAllMetadataOtherThanDebugLoc(MDForInst); + for (auto &MD : MDForInst) + visitMDNode(*MD.second); + return; + } + + if (auto *M = dyn_cast(&V)) { + visitMetadata(*M->getMetadata()); + return; + } + + if (auto *F = dyn_cast(&V)) { + for (Use &U : F->operands()) + visitValue(*U.get()); + for (auto &A : F->args()) + visitValue(A); + for (BasicBlock &BB : *F) + visitValue(BB); + return; + } + + User &U = cast(V); + for (auto &I : U.operands()) + visitValue(*I); +} + +void ValueVisitor::visitMetadata(Metadata &MD) { + if (auto *N = dyn_cast(&MD)) + visitMDNode(*N); + else if (auto *MDV = dyn_cast(&MD)) + visitValue(*MDV->getValue()); +} + +void ValueVisitor::visitMDNode(MDNode &MD) { + if (VisitedMDNode.insert(&MD).second) + for (Metadata *Op : MD.operands()) + if (Op) + visitMetadata(*Op); +} + +void ValueVisitor::run() { + for (auto &G : M.globals()) + visitValue(G); + for (auto &A : M.aliases()) + visitValue(A); + for (Function &F : M) + visitValue(F); + for (auto &IF : M.ifuncs()) + visitValue(IF); + for (auto &NMD : M.named_metadata()) + for (auto *MDOp : NMD.operands()) + visitMDNode(*MDOp); +} + +void llvm::visitAllValues(Module &M, std::function Visit) { + ValueVisitor Visitor(M, Visit); + Visitor.run(); +} + +void llvm::visitAllValues(const Module &M, + std::function Visit) { + visitAllValues(const_cast(M), [&](Value &V) { Visit(V); }); +} Index: lib/Linker/IRMover.cpp =================================================================== --- lib/Linker/IRMover.cpp +++ lib/Linker/IRMover.cpp @@ -18,6 +18,7 @@ #include "llvm/IR/GVMaterializer.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/TypeFinder.h" +#include "llvm/IR/ValueVisitor.h" #include "llvm/Support/Error.h" #include "llvm/Transforms/Utils/Cloning.h" #include @@ -320,7 +321,8 @@ if (StructType *OldT = DstStructTypesSet.findNonOpaque(ElementTypes, IsPacked)) { - STy->setName(""); + if (OldT != STy) + STy->setName(""); return *Entry = OldT; } @@ -1441,7 +1443,26 @@ return I == NonOpaqueStructTypes.end() ? false : *I == Ty; } +static void simplifyTypes(Module &M) { + TypeFinder StructTypes; + StructTypes.run(M, /* OnlyNamed */ false); + IRMover::IdentifiedStructTypeSet IdentifiedStructTypes; + for (StructType *Ty : StructTypes) { + if (Ty->isOpaque()) + IdentifiedStructTypes.addOpaque(Ty); + else + IdentifiedStructTypes.addNonOpaque(Ty); + } + TypeMapTy TypeMap(IdentifiedStructTypes); + visitAllValues(M, [&](Value &V) { + V.mutateType(TypeMap.get(V.getType())); + if (auto *GV = dyn_cast(&V)) + GV->mutateValueType(TypeMap.get(GV->getValueType())); + }); +} + IRMover::IRMover(Module &M) : Composite(M) { + simplifyTypes(M); TypeFinder StructTypes; StructTypes.run(M, /* OnlyNamed */ false); for (StructType *Ty : StructTypes) { Index: test/Linker/Inputs/struct-mapping.ll =================================================================== --- /dev/null +++ test/Linker/Inputs/struct-mapping.ll @@ -0,0 +1,4 @@ +%struct.Baz = type { i64, i64, %struct.Foo } +%struct.Foo = type { i64, i64 } + +@baz = global %struct.Baz zeroinitializer Index: test/Linker/struct-mapping.ll =================================================================== --- /dev/null +++ test/Linker/struct-mapping.ll @@ -0,0 +1,18 @@ +; RUN: llvm-link --initial-module=%s %p/Inputs/struct-mapping.ll -S -o - | FileCheck %s + +; Here we check that new type mapping merged isomorphic types. + +; CHECK-NOT: Foo +; CHECK: %struct.Bar = type { i64, i64 } +; CHECK-NEXT: %struct.Baz = type { i64, i64, %struct.Bar } +; CHECK-NOT: Foo + +; CHECK: @bar = global %struct.Bar zeroinitializer +; CHECK: @foo = global %struct.Bar zeroinitializer +; CHECK: @baz = global %struct.Baz zeroinitializer + +%struct.Bar = type { i64, i64 } +%struct.Foo = type { i64, i64 } + +@bar = global %struct.Bar zeroinitializer +@foo = global %struct.Foo zeroinitializer Index: tools/llvm-link/llvm-link.cpp =================================================================== --- tools/llvm-link/llvm-link.cpp +++ tools/llvm-link/llvm-link.cpp @@ -70,6 +70,11 @@ OutputFilename("o", cl::desc("Override output filename"), cl::init("-"), cl::value_desc("filename")); +static cl::opt + InitialModule("initial-module", + cl::desc("Link to existing destination module"), cl::init(""), + cl::value_desc("filename")); + static cl::opt Internalize("internalize", cl::desc("Internalize linked symbols")); @@ -360,7 +365,9 @@ if (!DisableDITypeMap) Context.enableDebugTypeODRUniquing(); - auto Composite = make_unique("llvm-link", Context); + auto Composite = InitialModule.empty() + ? make_unique("llvm-link", Context) + : loadFile(argv[0], InitialModule, Context); Linker L(*Composite); unsigned Flags = Linker::Flags::None;