[llvm-profdata] Stabilize iteration order for InstrProfWriter
authorFangrui Song <i@maskray.me>
Fri, 21 Jul 2023 01:31:41 +0000 (18:31 -0700)
committerFangrui Song <i@maskray.me>
Fri, 21 Jul 2023 01:31:41 +0000 (18:31 -0700)
If two functions are inserted to the same bucket, their order in the
serialized profile is dependent on StringMap iteration order, which is
not guaranteed to be deterministic.
(https://llvm.org/docs/ProgrammersManual.html#llvm-adt-stringmap-h).
Use a sort like we do in writeText.

llvm/lib/ProfileData/InstrProfWriter.cpp
llvm/test/tools/llvm-profdata/suppl-instr-with-sample.test

index 09cd096..b74d5c3 100644 (file)
@@ -413,9 +413,13 @@ Error InstrProfWriter::writeImpl(ProfOStream &OS) {
   InfoObj->CSSummaryBuilder = &CSISB;
 
   // Populate the hash table generator.
+  SmallVector<std::pair<StringRef, const ProfilingData *>, 0> OrderedData;
   for (const auto &I : FunctionData)
     if (shouldEncodeData(I.getValue()))
-      Generator.insert(I.getKey(), &I.getValue());
+      OrderedData.emplace_back((I.getKey()), &I.getValue());
+  llvm::sort(OrderedData, less_first());
+  for (const auto &I : OrderedData)
+    Generator.insert(I.first, I.second);
 
   // Write the header.
   IndexedInstrProf::Header Header;
index 4b53a35..20d4d21 100644 (file)
@@ -6,15 +6,15 @@ RUN:     -supplement-instr-with-sample=%p/Inputs/mix_sample.proftext \
 RUN:     -suppl-min-size-threshold=0 %p/Inputs/mix_instr.proftext -o %t
 RUN: llvm-profdata show %t -all-functions -counts | FileCheck %s --check-prefix=MIX1
 
+MIX1: foo:
+MIX1-NEXT: Hash: 0x0000000000000007
+MIX1-NEXT: Counters: 5
+MIX1-NEXT: Block counts: [12, 13, 0, 0, 0]
 MIX1: goo:
 MIX1-NEXT: Hash: 0x0000000000000005
 MIX1-NEXT: Counters: 3
 MIX1-NOT: Block counts:
 MIX1-SAME: <PseudoHot>
-MIX1: foo:
-MIX1-NEXT: Hash: 0x0000000000000007
-MIX1-NEXT: Counters: 5
-MIX1-NEXT: Block counts: [12, 13, 0, 0, 0]
 MIX1: moo:
 MIX1-NEXT: Hash: 0x0000000000000009
 MIX1-NEXT: Counters: 4
@@ -27,16 +27,16 @@ RUN:     -suppl-min-size-threshold=0 -zero-counter-threshold=0.5 \
 RUN:     -instr-prof-cold-threshold=30 %p/Inputs/mix_instr.proftext -o %t
 RUN: llvm-profdata show %t -all-functions -counts | FileCheck %s --check-prefix=MIX2
 
-MIX2: goo:
-MIX2-NEXT: Hash: 0x0000000000000005
-MIX2-NEXT: Counters: 3
-MIX2-NOT: Block counts:
-MIX2-SAME: <PseudoHot>
 MIX2: foo:
 MIX2-NEXT: Hash: 0x0000000000000007
 MIX2-NEXT: Counters: 5
 MIX2-NOT: Block counts:
 MIX2-SAME: <PseudoHot>
+MIX2: goo:
+MIX2-NEXT: Hash: 0x0000000000000005
+MIX2-NEXT: Counters: 3
+MIX2-NOT: Block counts:
+MIX2-SAME: <PseudoHot>
 MIX2: moo:
 MIX2-NEXT: Hash: 0x0000000000000009
 MIX2-NEXT: Counters: 4
@@ -49,15 +49,15 @@ RUN:     -suppl-min-size-threshold=0 -zero-counter-threshold=0.7 \
 RUN:     -instr-prof-cold-threshold=30 %p/Inputs/mix_instr.proftext -o %t
 RUN: llvm-profdata show %t -all-functions -counts | FileCheck %s --check-prefix=MIX3
 
+MIX3: foo:
+MIX3-NEXT: Hash: 0x0000000000000007
+MIX3-NEXT: Counters: 5
+MIX3-NEXT: Block counts: [1384, 1500, 0, 0, 0]
 MIX3: goo:
 MIX3-NEXT: Hash: 0x0000000000000005
 MIX3-NEXT: Counters: 3
 MIX3-NOT: Block counts:
 MIX3-SAME: <PseudoHot>
-MIX3: foo:
-MIX3-NEXT: Hash: 0x0000000000000007
-MIX3-NEXT: Counters: 5
-MIX3-NEXT: Block counts: [1384, 1500, 0, 0, 0]
 MIX3: moo:
 MIX3-NEXT: Hash: 0x0000000000000009
 MIX3-NEXT: Counters: 4
@@ -71,15 +71,15 @@ RUN:     -suppl-min-size-threshold=2 -zero-counter-threshold=0.7 \
 RUN:     -instr-prof-cold-threshold=30 %p/Inputs/mix_instr_small.proftext -o %t
 RUN: llvm-profdata show %t -all-functions -counts | FileCheck %s --check-prefix=MIX4
 
+MIX4: foo:
+MIX4-NEXT: Hash: 0x0000000000000007
+MIX4-NEXT: Counters: 1
+MIX4-NEXT: Block counts: [0]
 MIX4: goo:
 MIX4-NEXT: Hash: 0x0000000000000005
 MIX4-NEXT: Counters: 3
 MIX4-NOT: Block counts:
 MIX4-SAME: <PseudoHot>
-MIX4: foo:
-MIX4-NEXT: Hash: 0x0000000000000007
-MIX4-NEXT: Counters: 1
-MIX4-NEXT: Block counts: [0]
 MIX4: moo:
 MIX4-NEXT: Hash: 0x0000000000000009
 MIX4-NEXT: Counters: 1