[PATCH] [Core] Update references in parallel
Davide Italiano
davide at freebsd.org
Thu Mar 19 16:13:56 PDT 2015
I updated the patch to use a concurrent accumulator. It's just a prototype, and a little bit hack'ish but it worked for me (and it showed up a substantial improvement). I'm working in parallel on a concurrent hash map to see if it helps with other bottlenecks in the resolver.
In the meanwhile, Rafael, do you mind to re-run your tests with this patch applied in order to see if it shows up some improvement for you (or if it doesn't) ?
http://reviews.llvm.org/D8372
Files:
include/lld/Core/Parallel.h
include/lld/Core/Resolver.h
lib/Core/Resolver.cpp
Index: include/lld/Core/Parallel.h
===================================================================
--- include/lld/Core/Parallel.h
+++ include/lld/Core/Parallel.h
@@ -304,6 +304,38 @@
std::for_each(begin, end, func);
}
#endif
+
+template<typename T>
+struct node
+{
+ T data;
+ node *next;
+
+ node(const T data) : data(data), next(nullptr) {}
+ T getPayload() { return data; }
+ node<T>* getNext() { return next; };
+};
+
+template<typename T>
+class ConcurrentLIFOQueue
+{
+public:
+ ConcurrentLIFOQueue() : head(nullptr) {}
+
+ void insert(const T& data)
+ {
+ node<T>* new_node = new node<T>(data);
+ node<T>* old_head = head.load(std::memory_order_relaxed);
+ do {
+ new_node->next = old_head;
+ } while (!head.compare_exchange_weak(old_head, new_node,
+ std::memory_order_release,
+ std::memory_order_relaxed));
+ }
+ node<T>* getHead() { return head; }
+private:
+ std::atomic<node<T> *> head;
+};
} // end namespace lld
#endif
Index: include/lld/Core/Resolver.h
===================================================================
--- include/lld/Core/Resolver.h
+++ include/lld/Core/Resolver.h
@@ -91,6 +91,7 @@
std::set<const Atom *> _deadStripRoots;
llvm::DenseSet<const Atom *> _liveAtoms;
llvm::DenseSet<const Atom *> _deadAtoms;
+ ConcurrentLIFOQueue<const Atom *> _deadAtomsAccumulator;
std::unique_ptr<MergedFile> _result;
std::unordered_multimap<const Atom *, const Atom *> _reverseRef;
Index: lib/Core/Resolver.cpp
===================================================================
--- lib/Core/Resolver.cpp
+++ lib/Core/Resolver.cpp
@@ -341,7 +341,8 @@
// to the new defined atom
void Resolver::updateReferences() {
ScopedTask task(getDefaultDomain(), "updateReferences");
- for (const Atom *atom : _atoms) {
+ parallel_for_each(_atoms.begin(), _atoms.end(),
+ [&](const Atom *atom) {
if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(atom)) {
for (const Reference *ref : *defAtom) {
// A reference of type kindAssociate should't be updated.
@@ -351,14 +352,14 @@
if (ref->kindNamespace() == lld::Reference::KindNamespace::all &&
ref->kindValue() == lld::Reference::kindAssociate) {
if (_symbolTable.isCoalescedAway(atom))
- _deadAtoms.insert(ref->target());
+ _deadAtomsAccumulator.insert(ref->target());
continue;
}
const Atom *newTarget = _symbolTable.replacement(ref->target());
const_cast<Reference *>(ref)->setTarget(newTarget);
}
}
- }
+ });
}
// For dead code stripping, recursively mark atoms "live"
@@ -491,6 +492,12 @@
if (!resolveUndefines())
return false;
updateReferences();
+ // XXX: rewrite me please to use an iterator.
+ node<const Atom *>* tmp = _deadAtomsAccumulator.getHead();
+ while (tmp != nullptr) {
+ _deadAtoms.insert(tmp->getPayload());
+ tmp = tmp->getNext();
+ }
deadStripOptimize();
if (checkUndefines())
if (!_ctx.allowRemainingUndefines())
EMAIL PREFERENCES
http://reviews.llvm.org/settings/panel/emailpreferences/
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D8372.22318.patch
Type: text/x-patch
Size: 3137 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150319/c00084e1/attachment.bin>
More information about the llvm-commits
mailing list