From 233f5377999892630b8869a6010638b5d9b6ddc7 Mon Sep 17 00:00:00 2001 From: Nick Kledzik Date: Tue, 15 Jan 2013 00:17:57 +0000 Subject: [PATCH] Add new merge-by-content Merge attribute for use by anonymous constants and string literals which the linker should coalesce. llvm-svn: 172495 --- lld/include/lld/Core/DefinedAtom.h | 3 +- lld/lib/Core/Resolver.cpp | 7 +-- lld/lib/Core/SymbolTable.cpp | 14 ++++- .../ReaderWriter/YAML/ReaderWriterYAML.cpp | 1 + lld/test/constants-coalesce.objtxt | 60 +++++++++++++++++++ lld/test/cstring-coalesce.objtxt | 14 +++-- lld/test/darwin/hello-world.objtxt | 2 +- lld/test/fixups-unnamed.objtxt | 4 +- 8 files changed, 88 insertions(+), 17 deletions(-) create mode 100644 lld/test/constants-coalesce.objtxt diff --git a/lld/include/lld/Core/DefinedAtom.h b/lld/include/lld/Core/DefinedAtom.h index 5c5b4acb47ff..f3ab5434a1e5 100644 --- a/lld/include/lld/Core/DefinedAtom.h +++ b/lld/include/lld/Core/DefinedAtom.h @@ -101,8 +101,9 @@ public: mergeAsWeak, // is C++ inline definition that was not inlined, // but address was not taken, so atom can be hidden // by linker - mergeAsWeakAndAddressUsed // is C++ definition inline definition whose + mergeAsWeakAndAddressUsed,// is C++ definition inline definition whose // address was taken. + mergeByContent // merge with other constants with same content }; enum ContentType { diff --git a/lld/lib/Core/Resolver.cpp b/lld/lib/Core/Resolver.cpp index 8b426fae87fa..7e0d2e2895b7 100644 --- a/lld/lib/Core/Resolver.cpp +++ b/lld/lib/Core/Resolver.cpp @@ -110,11 +110,8 @@ void Resolver::doDefinedAtom(const DefinedAtom &atom) { // add to list of known atoms _atoms.push_back(&atom); - // non-static atoms need extra handling - if (atom.scope() != DefinedAtom::scopeTranslationUnit) { - // tell symbol table about non-static atoms - _symbolTable.add(atom); - } + // tell symbol table + _symbolTable.add(atom); if (_options.deadCodeStripping()) { // add to set of dead-strip-roots, all symbols that diff --git a/lld/lib/Core/SymbolTable.cpp b/lld/lib/Core/SymbolTable.cpp index b3fe8e8a50e5..1c7ea99ff051 100644 --- a/lld/lib/Core/SymbolTable.cpp +++ b/lld/lib/Core/SymbolTable.cpp @@ -46,11 +46,16 @@ void SymbolTable::add(const AbsoluteAtom &atom) { } void SymbolTable::add(const DefinedAtom &atom) { - assert(atom.scope() != DefinedAtom::scopeTranslationUnit); - if ( !atom.name().empty() ) { + if (!atom.name().empty() && + (atom.scope() != DefinedAtom::scopeTranslationUnit)) { + // Named atoms cannot be merged by content. + assert(atom.merge() != DefinedAtom::mergeByContent); + // Track named atoms that are not scoped to file (static). this->addByName(atom); } - else { + else if ( atom.merge() == DefinedAtom::mergeByContent ) { + // Named atoms cannot be merged by content. + assert(atom.name().empty()); this->addByContent(atom); } } @@ -123,6 +128,7 @@ static MergeResolution mergeSelect(DefinedAtom::Merge first, void SymbolTable::addByName(const Atom & newAtom) { StringRef name = newAtom.name(); + assert(!name.empty()); const Atom *existing = this->findByName(name); if (existing == nullptr) { // Name is not in symbol table yet, add it associate with this atom. @@ -283,6 +289,8 @@ bool SymbolTable::AtomMappingInfo::isEqual(const DefinedAtom * const l, } void SymbolTable::addByContent(const DefinedAtom & newAtom) { + // Currently only read-only constants can be merged. + assert(newAtom.permissions() == DefinedAtom::permR__); AtomContentSet::iterator pos = _contentTable.find(&newAtom); if ( pos == _contentTable.end() ) { _contentTable.insert(&newAtom); diff --git a/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp b/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp index 0581c2e056ad..310e8b416549 100644 --- a/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp +++ b/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp @@ -351,6 +351,7 @@ struct ScalarEnumerationTraits { io.enumCase(value, "as-weak", lld::DefinedAtom::mergeAsWeak); io.enumCase(value, "as-addressed-weak", lld::DefinedAtom::mergeAsWeakAndAddressUsed); + io.enumCase(value, "by-content", lld::DefinedAtom::mergeByContent); } }; diff --git a/lld/test/constants-coalesce.objtxt b/lld/test/constants-coalesce.objtxt new file mode 100644 index 000000000000..da388e50fe38 --- /dev/null +++ b/lld/test/constants-coalesce.objtxt @@ -0,0 +1,60 @@ +# RUN: lld-core %s | FileCheck %s + +# +# Test that duplicate merge-by-content anonymous constants are coalesced +# and non-mergable duplicate constants are not coalesced. +# + +--- +defined-atoms: + - ref-name: L4-byte + type: constant + merge: by-content + content: [ 01, 02, 03, 04 ] + + - ref-name: L8-byte + type: constant + merge: by-content + content: [ 01, 23, 45, 67, 89, AB, CD, EF ] + + - ref-name: L1 + type: constant + content: [ 01, 02 ] +--- +defined-atoms: + - ref-name: L1 + type: constant + content: [ 01, 02 ] + - ref-name: L2 + type: constant + merge: by-content + content: [ 01, 02, 03, 04 ] +--- +defined-atoms: + - ref-name: L2 + type: constant + merge: by-content + content: [ 01, 23, 45, 67, 89, AB, CD, EF ] + - ref-name: L3 + type: constant + merge: by-content + content: [ 01, 02, 03 ] +... + +# CHECK-NOT: name: +# CHECK: type: constant +# CHECK: content: [ 01, 02, 03, 04 ] +# CHECK: merge: by-content +# CHECK: type: constant +# CHECK: content: [ 01, 23, 45, 67, 89, AB, CD, EF ] +# CHECK: merge: by-content +# CHECK: type: constant +# CHECK: content: [ 01, 02 ] +# CHECK: type: constant +# CHECK: content: [ 01, 02 ] +# CHECK: type: constant +# CHECK: content: [ 01, 02, 03 ] +# CHECK: merge: by-content +# CHECK: ... + + diff --git a/lld/test/cstring-coalesce.objtxt b/lld/test/cstring-coalesce.objtxt index 5b37acca5c7d..5723299c1105 100644 --- a/lld/test/cstring-coalesce.objtxt +++ b/lld/test/cstring-coalesce.objtxt @@ -7,31 +7,35 @@ --- defined-atoms: - ref-name: L0 - scope: hidden type: c-string + merge: by-content content: [ 68, 65, 6c, 6c, 6f, 00 ] - ref-name: L1 - scope: hidden type: c-string + merge: by-content content: [ 74, 68, 65, 72, 65, 00 ] --- defined-atoms: - ref-name: L2 - scope: hidden type: c-string + merge: by-content content: [ 68, 65, 6c, 6c, 6f, 00 ] --- defined-atoms: - ref-name: L2 - scope: hidden type: c-string + merge: by-content content: [ 74, 68, 65, 72, 65, 00 ] ... +# CHECK-NOT: name: # CHECK: type: c-string # CHECK: content: [ 68, 65, 6C, 6C, 6F, 00 ] +# CHECK: merge: by-content # CHECK: type: c-string # CHECK: content: [ 74, 68, 65, 72, 65, 00 ] -# CHECK-NOT: name: +# CHECK: merge: by-content # CHECK: ... + + diff --git a/lld/test/darwin/hello-world.objtxt b/lld/test/darwin/hello-world.objtxt index 3b99933eb336..0d96c0746b04 100644 --- a/lld/test/darwin/hello-world.objtxt +++ b/lld/test/darwin/hello-world.objtxt @@ -21,8 +21,8 @@ defined-atoms: target: _printf - ref-name: LC1 - scope: hidden type: c-string + merge: by-content content: [ 68, 65, 6C, 6C, 6F, 0A, 00 ] shared-library-atoms: diff --git a/lld/test/fixups-unnamed.objtxt b/lld/test/fixups-unnamed.objtxt index 20cf373580e4..2c3d7aa09d95 100644 --- a/lld/test/fixups-unnamed.objtxt +++ b/lld/test/fixups-unnamed.objtxt @@ -20,13 +20,13 @@ defined-atoms: - ref-name: LC1 - scope: hidden type: c-string + merge: by-content content: [ 68, 65, 6c, 6c, 6f, 00 ] - ref-name: LC2 - scope: hidden type: c-string + merge: by-content content: [ 74, 68, 65, 72, 65, 00 ]