[llvm] [DWARFLinker] Make ODR uniquing deterministic (PR #194777)

via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 29 06:02:13 PDT 2026


================
@@ -1419,46 +1419,42 @@ DIE *CompileUnit::allocateTypeDie(TypeEntryBody *TypeDescriptor,
                                   DIEGenerator &TypeDIEGenerator,
                                   dwarf::Tag DieTag, bool IsDeclaration,
                                   bool IsParentDeclaration) {
-  DIE *DefinitionDie = TypeDescriptor->Die;
-  // Do not allocate any new DIE if definition DIE is already met.
-  if (DefinitionDie)
-    return nullptr;
-
-  DIE *DeclarationDie = TypeDescriptor->DeclarationDie;
-  bool OldParentIsDeclaration = TypeDescriptor->ParentIsDeclaration;
-
-  if (IsDeclaration && !DeclarationDie) {
-    // Alocate declaration DIE.
-    DIE *NewDie = TypeDIEGenerator.createDIE(DieTag, 0);
-    if (TypeDescriptor->DeclarationDie.compare_exchange_strong(DeclarationDie,
-                                                               NewDie))
-      return NewDie;
-  } else if (IsDeclaration && !IsParentDeclaration && OldParentIsDeclaration) {
-    // Overwrite existing declaration DIE if it's parent is also an declaration
-    // while parent of current declaration DIE is a definition.
-    if (TypeDescriptor->ParentIsDeclaration.compare_exchange_strong(
-            OldParentIsDeclaration, false)) {
-      DIE *NewDie = TypeDIEGenerator.createDIE(DieTag, 0);
-      TypeDescriptor->DeclarationDie = NewDie;
-      return NewDie;
-    }
-  } else if (!IsDeclaration && IsParentDeclaration && !DeclarationDie) {
-    // Alocate declaration DIE since parent of current DIE is marked as
-    // declaration.
-    DIE *NewDie = TypeDIEGenerator.createDIE(DieTag, 0);
-    if (TypeDescriptor->DeclarationDie.compare_exchange_strong(DeclarationDie,
-                                                               NewDie))
-      return NewDie;
-  } else if (!IsDeclaration && !IsParentDeclaration) {
-    // Allocate definition DIE.
-    DIE *NewDie = TypeDIEGenerator.createDIE(DieTag, 0);
-    if (TypeDescriptor->Die.compare_exchange_strong(DefinitionDie, NewDie)) {
+  // Use a per-type spinlock and CU priority to ensure the earliest CU in link
+  // order always wins the type slot, producing deterministic output regardless
+  // of thread scheduling.
+  unsigned Priority = getDeterministicPriority();
+
+  // Speculatively allocate the DIE outside the lock so the critical section
+  // only covers the priority check and pointer store. If we lose, the DIE
+  // is leaked into the bump allocator.
+  DIE *NewDie = TypeDIEGenerator.createDIE(DieTag, 0);
----------------
alx32 wrote:

Every CU that's the lowest-priority seen so far fully clones and emits accelerator records, only to be filtered later by `getFinalDie()`. When several CUs race on the same type, most of that work gets thrown away — the leaked DIEs, patches, and accel records all pile up in the bump allocator. If it's straightforward, could we check priority first (load `DiePriority`/`DeclarationDiePriority` under the lock) and only `createDIE`/`clone`/`save` when this CU can actually win?


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


More information about the llvm-commits mailing list