BitcodeWriter: Emit distinct nodes before uniqued nodes

When an operand of a distinct node hasn't been read yet, the reader can
use a DistinctMDOperandPlaceholder.  This is much cheaper than forward
referencing from a uniqued node.  Change
ValueEnumerator::organizeMetadata to partition distinct nodes and
uniqued nodes to reduce the overhead of cycles broken by distinct nodes.

Mehdi measured this for me; this removes most of the RAUW from the
importing step of -flto=thin, even after a WIP patch that removes
string-based DITypeRefs (introducing many more cycles to the metadata
graph).

llvm-svn: 267276
This commit is contained in:
Duncan P. N. Exon Smith 2016-04-23 04:42:39 +00:00
parent 004eb55feb
commit 1483fff271
2 changed files with 36 additions and 6 deletions

View File

@ -647,6 +647,22 @@ void ValueEnumerator::EnumerateFunctionLocalMetadata(
EnumerateValue(Local->getValue());
}
static unsigned getMetadataTypeOrder(const Metadata *MD) {
// Strings are emitted in bulk and must come first.
if (isa<MDString>(MD))
return 0;
// ConstantAsMetadata doesn't reference anything. We may as well shuffle it
// to the front since we can detect it.
auto *N = dyn_cast<MDNode>(MD);
if (!N)
return 1;
// The reader is fast forward references for distinct node operands, but slow
// when uniqued operands are unresolved.
return N->isDistinct() ? 2 : 3;
}
void ValueEnumerator::organizeMetadata() {
assert(MetadataMap.size() == MDs.size() &&
"Metadata map and vector out of sync");
@ -668,14 +684,10 @@ void ValueEnumerator::organizeMetadata() {
// be unique, the result of std::sort will be deterministic. There's no need
// for std::stable_sort.
std::sort(Order.begin(), Order.end(), [this](MDIndex LHS, MDIndex RHS) {
return std::make_tuple(LHS.F, !isa<MDString>(LHS.get(MDs)), LHS.ID) <
std::make_tuple(RHS.F, !isa<MDString>(RHS.get(MDs)), RHS.ID);
return std::make_tuple(LHS.F, getMetadataTypeOrder(LHS.get(MDs)), LHS.ID) <
std::make_tuple(RHS.F, getMetadataTypeOrder(RHS.get(MDs)), RHS.ID);
});
// Return early if nothing is moving to functions and there are no strings.
if (!Order.back().F && !isa<MDString>(Order.front().get(MDs)))
return;
// Rebuild MDs, index the metadata ranges for each function in FunctionMDs,
// and fix up MetadataMap.
std::vector<const Metadata *> OldMDs = std::move(MDs);

View File

@ -0,0 +1,18 @@
; RUN: llvm-as <%s | llvm-bcanalyzer -dump | FileCheck %s
; Check that distinct nodes are emitted before uniqued nodes, even if that
; breaks post-order traversals.
; Nodes in this testcase are numbered to match how they are referenced in
; bitcode. !1 is referenced as opN=1.
; CHECK: <DISTINCT_NODE op0=2/>
!1 = distinct !{!2}
; CHECK-NEXT: <NODE op0=1/>
!2 = !{!1}
; Note: named metadata nodes are not cannot reference null so their operands
; are numbered off-by-one.
; CHECK-NEXT: <NAME
; CHECK-NEXT: <NAMED_NODE op0=1/>
!named = !{!2}