From: Rafael Espindola Date: Tue, 25 Nov 2014 05:59:24 +0000 (+0000) Subject: Fix overly aggressive type merging. X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=commitdiff_plain;h=842d2b62ed84c8d067d43bbdb6194b0aafeaa098 Fix overly aggressive type merging. If we find out that two types are *not* isomorphic, we learn nothing about opaque sub types in both the source and destination. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@222727 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Linker/LinkModules.cpp b/lib/Linker/LinkModules.cpp index a8dc324daa2..e57a37fb4a0 100644 --- a/lib/Linker/LinkModules.cpp +++ b/lib/Linker/LinkModules.cpp @@ -107,12 +107,23 @@ void TypeMapTy::addTypeMapping(Type *DstTy, Type *SrcTy) { // Check to see if these types are recursively isomorphic and establish a // mapping between them if so. - if (!areTypesIsomorphic(DstTy, SrcTy)) { - // Oops, they aren't isomorphic. Just discard this request by rolling out - // any speculative mappings we've established. - for (unsigned i = 0, e = SpeculativeTypes.size(); i != e; ++i) - MappedTypes.erase(SpeculativeTypes[i]); + if (areTypesIsomorphic(DstTy, SrcTy)) { + SpeculativeTypes.clear(); + return; + } + + // Oops, they aren't isomorphic. Just discard this request by rolling out + // any speculative mappings we've established. + unsigned Removed = 0; + for (unsigned I = 0, E = SpeculativeTypes.size(); I != E; ++I) { + Type *SrcTy = SpeculativeTypes[I]; + auto Iter = MappedTypes.find(SrcTy); + auto *DstTy = dyn_cast(Iter->second); + if (DstTy && DstResolvedOpaqueTypes.erase(DstTy)) + Removed++; + MappedTypes.erase(Iter); } + SrcDefinitionsToResolve.resize(SrcDefinitionsToResolve.size() - Removed); SpeculativeTypes.clear(); } @@ -147,14 +158,14 @@ bool TypeMapTy::areTypesIsomorphic(Type *DstTy, Type *SrcTy) { // Mapping a non-opaque source type to an opaque dest. If this is the first // type that we're mapping onto this destination type then we succeed. Keep - // the dest, but fill it in later. This doesn't need to be speculative. If - // this is the second (different) type that we're trying to map onto the - // same opaque type then we fail. + // the dest, but fill it in later. If this is the second (different) type + // that we're trying to map onto the same opaque type then we fail. if (cast(DstTy)->isOpaque()) { // We can only map one source type onto the opaque destination type. if (!DstResolvedOpaqueTypes.insert(cast(DstTy)).second) return false; SrcDefinitionsToResolve.push_back(SSTy); + SpeculativeTypes.push_back(SrcTy); Entry = DstTy; return true; } diff --git a/test/Linker/Inputs/type-unique-opaque.ll b/test/Linker/Inputs/type-unique-opaque.ll new file mode 100644 index 00000000000..872b601f691 --- /dev/null +++ b/test/Linker/Inputs/type-unique-opaque.ll @@ -0,0 +1,6 @@ +%t = type { i8 } +%t2 = type { %t*, i16 } + +define %t2* @f() { + ret %t2* null +} diff --git a/test/Linker/type-unique-opaque.ll b/test/Linker/type-unique-opaque.ll new file mode 100644 index 00000000000..b4f69669921 --- /dev/null +++ b/test/Linker/type-unique-opaque.ll @@ -0,0 +1,16 @@ +; RUN: llvm-link -S %s %p/Inputs/type-unique-opaque.ll | FileCheck %s + +; Test that a failed attempt at merging %u2 and %t2 (for the other file) will +; not cause %u and %t to get merged. + +; CHECK: %u = type opaque +; CHECK: define %u* @g() { + +%u = type opaque +%u2 = type { %u*, i8 } + +declare %u2* @f() + +define %u* @g() { + ret %u* null +}