[llvm] [BOLT] fix race condition in multi-threaded DWO type unit processing (PR #197359)

via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 2 00:14:12 PDT 2026


================
@@ -283,6 +283,73 @@ void DIEBuilder::buildTypeUnits(DebugStrOffsetsWriter *StrOffsetWriter,
   }
 }
 
+static void collectReferencedTypeSignatures(DWARFDie Die,
+                                            DenseSet<uint64_t> &ProcessedTU,
+                                            SmallVectorImpl<uint64_t> &TUlist) {
+  SmallVector<DWARFDie, 8> DIElist;
+  DIElist.push_back(Die);
+
+  while (!DIElist.empty()) {
+    DWARFDie Current = DIElist.pop_back_val();
+    if (!Current)
+      continue;
+
+    for (const DWARFAttribute &Attr : Current.attributes()) {
+      if (Attr.Value.getForm() != dwarf::DW_FORM_ref_sig8)
+        continue;
+      if (const std::optional<uint64_t> Signature =
+              Attr.Value.getAsSignatureReference())
+        if (ProcessedTU.insert(*Signature).second)
+          TUlist.push_back(*Signature);
+    }
+
+    for (DWARFDie Child : Current.children())
+      DIElist.push_back(Child);
+  }
+}
+
+void DIEBuilder::buildDWPTypeUnitsForUnit(DWARFUnit &U) {
+  // Avoid processing the same type unit multiple times.
+  DenseSet<uint64_t> ProcessedTU;
+  SmallVector<uint64_t, 8> TUlist;
+  // Collecting signatures of type units referenced by this unit.
+  collectReferencedTypeSignatures(U.getUnitDIE(), ProcessedTU, TUlist);
+
+  // addressing type units referenced.
+  for (unsigned I = 0; I != TUlist.size(); ++I) {
+    const uint64_t Signature = TUlist[I];
+    DWARFTypeUnit *TU = DwarfContext->getTypeUnitForHash(Signature, true);
+    if (!TU)
+      continue;
+
+    getState().Type = TU->getVersion() < 5 ? ProcessingType::DWARF4TUs
+                                           : ProcessingType::DWARF5TUs;
+    if (!registerUnit(*TU, false))
+      continue;
+
+    const std::optional<uint32_t> UnitId = getUnitId(*TU);
+    if (!UnitId || getState().CloneUnitCtxMap[*UnitId].IsConstructed)
+      continue;
+
+    collectReferencedTypeSignatures(TU->getUnitDIE(), ProcessedTU, TUlist);
+  }
+
+  // Ensure deterministic order of processing type units
+  auto SortByOffset = [](const DWARFUnit *A, const DWARFUnit *B) {
----------------
Thrrreeee wrote:

> Isn't this already enforced by the structure of DWARF? Even if we process each CU in parallel it's internal structure is deterministic?

Its internal structure are deterministic when process each CU in parallel. But there the TU vector order here is not derived from the original TU order. In the DWP path, registerUnit() is called according to the     
  order in which DW_FORM_ref_sig8 references are discovered from the current CU/TU graph. That first-discovery order can differ from the original type-unit offset order, and the vector 
  is later used directly for emission / TU index generation. Sorting by unit offset restores a input-order before emitting.  

If you think the traversal order is already sufficient here, we can also drop this sort. However, we may also need to modify the corresponding testcases.

https://github.com/llvm/llvm-project/pull/197359


More information about the llvm-commits mailing list