[llvm] [KeyInstr] Add Atom Group waterline to LLVMContext (PR #133478)

Orlando Cazalet-Hyams via llvm-commits llvm-commits at lists.llvm.org
Tue May 6 02:30:44 PDT 2025


https://github.com/OCHyams updated https://github.com/llvm/llvm-project/pull/133478

>From 5ff06c748337e55be93446bb7c066da955ff4cc1 Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Tue, 18 Mar 2025 12:40:14 +0000
Subject: [PATCH 1/8] [KeyInstr] Add fields to DILocation behind compile time
 flag

The definition EXPERIMENTAL_KEY_INSTRUCTIONS is controlled by cmake flag
LLVM_EXPERIMENTAL_KEY_INSTRUCTIONS.

Add IR read-write roundtrip test in a directory that is unsupported unless
the CMake flag is enabled.
---
 llvm/include/llvm/IR/DebugInfoMetadata.h      | 46 ++++++++++++++-----
 llvm/lib/AsmParser/LLParser.cpp               | 10 ++--
 llvm/lib/IR/AsmWriter.cpp                     |  2 +
 llvm/lib/IR/DebugInfoMetadata.cpp             | 24 +++++++---
 llvm/lib/IR/LLVMContextImpl.h                 | 17 +++++--
 llvm/test/CMakeLists.txt                      |  1 +
 .../KeyInstructions/Generic/parse.ll          | 19 ++++++++
 .../DebugInfo/KeyInstructions/lit.local.cfg   |  2 +
 llvm/test/lit.site.cfg.py.in                  |  1 +
 9 files changed, 95 insertions(+), 27 deletions(-)
 create mode 100644 llvm/test/DebugInfo/KeyInstructions/Generic/parse.ll
 create mode 100644 llvm/test/DebugInfo/KeyInstructions/lit.local.cfg

diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h
index 174ff09f56bdf..03b162737d0a3 100644
--- a/llvm/include/llvm/IR/DebugInfoMetadata.h
+++ b/llvm/include/llvm/IR/DebugInfoMetadata.h
@@ -2235,44 +2235,67 @@ class DISubprogram : public DILocalScope {
 class DILocation : public MDNode {
   friend class LLVMContextImpl;
   friend class MDNode;
+#ifdef EXPERIMENTAL_KEY_INSTRUCTIONS
+  uint64_t AtomGroup : 61;
+  uint8_t AtomRank : 3;
+#endif
 
   DILocation(LLVMContext &C, StorageType Storage, unsigned Line,
-             unsigned Column, ArrayRef<Metadata *> MDs, bool ImplicitCode);
+             unsigned Column, uint64_t AtomGroup, uint8_t AtomRank,
+             ArrayRef<Metadata *> MDs, bool ImplicitCode);
   ~DILocation() { dropAllReferences(); }
 
   static DILocation *getImpl(LLVMContext &Context, unsigned Line,
                              unsigned Column, Metadata *Scope,
                              Metadata *InlinedAt, bool ImplicitCode,
+                             uint64_t AtomGroup, uint8_t AtomRank,
                              StorageType Storage, bool ShouldCreate = true);
   static DILocation *getImpl(LLVMContext &Context, unsigned Line,
                              unsigned Column, DILocalScope *Scope,
                              DILocation *InlinedAt, bool ImplicitCode,
+                             uint64_t AtomGroup, uint8_t AtomRank,
                              StorageType Storage, bool ShouldCreate = true) {
     return getImpl(Context, Line, Column, static_cast<Metadata *>(Scope),
-                   static_cast<Metadata *>(InlinedAt), ImplicitCode, Storage,
-                   ShouldCreate);
+                   static_cast<Metadata *>(InlinedAt), ImplicitCode, AtomGroup,
+                   AtomRank, Storage, ShouldCreate);
   }
 
   TempDILocation cloneImpl() const {
     // Get the raw scope/inlinedAt since it is possible to invoke this on
     // a DILocation containing temporary metadata.
     return getTemporary(getContext(), getLine(), getColumn(), getRawScope(),
-                        getRawInlinedAt(), isImplicitCode());
+                        getRawInlinedAt(), isImplicitCode(), getAtomGroup(),
+                        getAtomRank());
   }
-
 public:
+  uint64_t getAtomGroup() const {
+#ifdef EXPERIMENTAL_KEY_INSTRUCTIONS
+    return AtomGroup;
+#endif
+    return 0;
+  }
+  uint8_t getAtomRank() const {
+#ifdef EXPERIMENTAL_KEY_INSTRUCTIONS
+    return AtomRank;
+#endif
+    return 0;
+  }
+
   // Disallow replacing operands.
   void replaceOperandWith(unsigned I, Metadata *New) = delete;
 
   DEFINE_MDNODE_GET(DILocation,
                     (unsigned Line, unsigned Column, Metadata *Scope,
-                     Metadata *InlinedAt = nullptr, bool ImplicitCode = false),
-                    (Line, Column, Scope, InlinedAt, ImplicitCode))
+                     Metadata *InlinedAt = nullptr, bool ImplicitCode = false,
+                     uint64_t AtomGroup = 0, uint8_t AtomRank = 0),
+                    (Line, Column, Scope, InlinedAt, ImplicitCode, AtomGroup,
+                     AtomRank))
   DEFINE_MDNODE_GET(DILocation,
                     (unsigned Line, unsigned Column, DILocalScope *Scope,
-                     DILocation *InlinedAt = nullptr,
-                     bool ImplicitCode = false),
-                    (Line, Column, Scope, InlinedAt, ImplicitCode))
+                     DILocation *InlinedAt = nullptr, bool ImplicitCode = false,
+                     uint64_t AtomGroup = 0, uint8_t AtomRank = 0),
+                    (Line, Column, Scope, InlinedAt, ImplicitCode, AtomGroup,
+                     AtomRank))
 
   /// Return a (temporary) clone of this.
   TempDILocation clone() const { return cloneImpl(); }
@@ -2647,7 +2670,8 @@ DILocation::cloneWithDiscriminator(unsigned Discriminator) const {
   DILexicalBlockFile *NewScope =
       DILexicalBlockFile::get(getContext(), Scope, getFile(), Discriminator);
   return DILocation::get(getContext(), getLine(), getColumn(), NewScope,
-                         getInlinedAt());
+                         getInlinedAt(), isImplicitCode(), getAtomGroup(),
+                         getAtomRank());
 }
 
 unsigned DILocation::getBaseDiscriminator() const {
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 370d124dc42b4..0772395e8279b 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -5326,13 +5326,15 @@ bool LLParser::parseDILocation(MDNode *&Result, bool IsDistinct) {
   OPTIONAL(column, ColumnField, );                                             \
   REQUIRED(scope, MDField, (/* AllowNull */ false));                           \
   OPTIONAL(inlinedAt, MDField, );                                              \
-  OPTIONAL(isImplicitCode, MDBoolField, (false));
+  OPTIONAL(isImplicitCode, MDBoolField, (false));                              \
+  OPTIONAL(atomGroup, MDUnsignedField, (0, UINT64_MAX));                       \
+  OPTIONAL(atomRank, MDUnsignedField, (0, UINT8_MAX));
   PARSE_MD_FIELDS();
 #undef VISIT_MD_FIELDS
 
-  Result =
-      GET_OR_DISTINCT(DILocation, (Context, line.Val, column.Val, scope.Val,
-                                   inlinedAt.Val, isImplicitCode.Val));
+  Result = GET_OR_DISTINCT(
+      DILocation, (Context, line.Val, column.Val, scope.Val, inlinedAt.Val,
+                   isImplicitCode.Val, atomGroup.Val, atomRank.Val));
   return false;
 }
 
diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index 80b1648614eda..12edf6fcd510c 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -2103,6 +2103,8 @@ static void writeDILocation(raw_ostream &Out, const DILocation *DL,
   Printer.printMetadata("inlinedAt", DL->getRawInlinedAt());
   Printer.printBool("isImplicitCode", DL->isImplicitCode(),
                     /* Default */ false);
+  Printer.printInt("atomGroup", DL->getAtomGroup());
+  Printer.printInt<unsigned>("atomRank", DL->getAtomRank());
   Out << ")";
 }
 
diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp
index 4f1b9e836120e..bfe956d46dd7e 100644
--- a/llvm/lib/IR/DebugInfoMetadata.cpp
+++ b/llvm/lib/IR/DebugInfoMetadata.cpp
@@ -63,12 +63,19 @@ DebugVariableAggregate::DebugVariableAggregate(const DbgVariableIntrinsic *DVI)
                     DVI->getDebugLoc()->getInlinedAt()) {}
 
 DILocation::DILocation(LLVMContext &C, StorageType Storage, unsigned Line,
-                       unsigned Column, ArrayRef<Metadata *> MDs,
-                       bool ImplicitCode)
-    : MDNode(C, DILocationKind, Storage, MDs) {
+                       unsigned Column, uint64_t AtomGroup, uint8_t AtomRank,
+                       ArrayRef<Metadata *> MDs, bool ImplicitCode)
+    : MDNode(C, DILocationKind, Storage, MDs)
+#ifdef EXPERIMENTAL_KEY_INSTRUCTIONS
+      ,
+      AtomGroup(AtomGroup), AtomRank(AtomRank)
+#endif
+{
+#ifdef EXPERIMENTAL_KEY_INSTRUCTIONS
+  assert(AtomRank <= 7 && "AtomRank number should fit in 3 bits");
+#endif
   assert((MDs.size() == 1 || MDs.size() == 2) &&
          "Expected a scope and optional inlined-at");
-
   // Set line and column.
   assert(Column < (1u << 16) && "Expected 16-bit column");
 
@@ -87,6 +94,7 @@ static void adjustColumn(unsigned &Column) {
 DILocation *DILocation::getImpl(LLVMContext &Context, unsigned Line,
                                 unsigned Column, Metadata *Scope,
                                 Metadata *InlinedAt, bool ImplicitCode,
+                                uint64_t AtomGroup, uint8_t AtomRank,
                                 StorageType Storage, bool ShouldCreate) {
   // Fixup column.
   adjustColumn(Column);
@@ -94,7 +102,8 @@ DILocation *DILocation::getImpl(LLVMContext &Context, unsigned Line,
   if (Storage == Uniqued) {
     if (auto *N = getUniqued(Context.pImpl->DILocations,
                              DILocationInfo::KeyTy(Line, Column, Scope,
-                                                   InlinedAt, ImplicitCode)))
+                                                   InlinedAt, ImplicitCode,
+                                                   AtomGroup, AtomRank)))
       return N;
     if (!ShouldCreate)
       return nullptr;
@@ -106,8 +115,9 @@ DILocation *DILocation::getImpl(LLVMContext &Context, unsigned Line,
   Ops.push_back(Scope);
   if (InlinedAt)
     Ops.push_back(InlinedAt);
-  return storeImpl(new (Ops.size(), Storage) DILocation(
-                       Context, Storage, Line, Column, Ops, ImplicitCode),
+  return storeImpl(new (Ops.size(), Storage)
+                       DILocation(Context, Storage, Line, Column, AtomGroup,
+                                  AtomRank, Ops, ImplicitCode),
                    Storage, Context.pImpl->DILocations);
 }
 
diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h
index 71369772f4529..dafb6b8308d77 100644
--- a/llvm/lib/IR/LLVMContextImpl.h
+++ b/llvm/lib/IR/LLVMContextImpl.h
@@ -315,23 +315,30 @@ template <> struct MDNodeKeyImpl<DILocation> {
   Metadata *Scope;
   Metadata *InlinedAt;
   bool ImplicitCode;
+  uint64_t AtomGroup : 61;
+  uint8_t AtomRank : 3;
 
   MDNodeKeyImpl(unsigned Line, unsigned Column, Metadata *Scope,
-                Metadata *InlinedAt, bool ImplicitCode)
+                Metadata *InlinedAt, bool ImplicitCode, uint64_t AtomGroup,
+                uint8_t AtomRank)
       : Line(Line), Column(Column), Scope(Scope), InlinedAt(InlinedAt),
-        ImplicitCode(ImplicitCode) {}
+        ImplicitCode(ImplicitCode), AtomGroup(AtomGroup), AtomRank(AtomRank) {}
+
   MDNodeKeyImpl(const DILocation *L)
       : Line(L->getLine()), Column(L->getColumn()), Scope(L->getRawScope()),
-        InlinedAt(L->getRawInlinedAt()), ImplicitCode(L->isImplicitCode()) {}
+        InlinedAt(L->getRawInlinedAt()), ImplicitCode(L->isImplicitCode()),
+        AtomGroup(L->getAtomGroup()), AtomRank(L->getAtomRank()) {}
 
   bool isKeyOf(const DILocation *RHS) const {
     return Line == RHS->getLine() && Column == RHS->getColumn() &&
            Scope == RHS->getRawScope() && InlinedAt == RHS->getRawInlinedAt() &&
-           ImplicitCode == RHS->isImplicitCode();
+           ImplicitCode == RHS->isImplicitCode() &&
+           AtomGroup == RHS->getAtomGroup() && AtomRank == RHS->getAtomRank();
   }
 
   unsigned getHashValue() const {
-    return hash_combine(Line, Column, Scope, InlinedAt, ImplicitCode);
+    return hash_combine(Line, Column, Scope, InlinedAt, ImplicitCode, AtomGroup,
+                        AtomRank);
   }
 };
 
diff --git a/llvm/test/CMakeLists.txt b/llvm/test/CMakeLists.txt
index 66849002eb470..2a6135da9a61e 100644
--- a/llvm/test/CMakeLists.txt
+++ b/llvm/test/CMakeLists.txt
@@ -29,6 +29,7 @@ llvm_canonicalize_cmake_booleans(
   LLVM_INCLUDE_SPIRV_TOOLS_TESTS
   LLVM_APPEND_VC_REV
   LLVM_HAS_LOGF128
+  LLVM_EXPERIMENTAL_KEY_INSTRUCTIONS
   )
 
 configure_lit_site_cfg(
diff --git a/llvm/test/DebugInfo/KeyInstructions/Generic/parse.ll b/llvm/test/DebugInfo/KeyInstructions/Generic/parse.ll
new file mode 100644
index 0000000000000..33219a582fee8
--- /dev/null
+++ b/llvm/test/DebugInfo/KeyInstructions/Generic/parse.ll
@@ -0,0 +1,19 @@
+; RUN: opt %s -o - -S| FileCheck %s
+
+; CHECK: !DILocation(line: 1, column: 11, scope: ![[#]], atomGroup: 1, atomRank: 1)
+
+define dso_local void @f() !dbg !10 {
+entry:
+  ret void, !dbg !13
+}
+
+!llvm.module.flags = !{!3}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 21.0.0git", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "test.cpp", directory: "/")
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!9 = !{!"clang version 21.0.0git"}
+!10 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 1, type: !11, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0)
+!11 = !DISubroutineType(types: !12)
+!12 = !{null}
+!13 = !DILocation(line: 1, column: 11, scope: !10, atomGroup: 1, atomRank: 1)
diff --git a/llvm/test/DebugInfo/KeyInstructions/lit.local.cfg b/llvm/test/DebugInfo/KeyInstructions/lit.local.cfg
new file mode 100644
index 0000000000000..482bd5c8ac251
--- /dev/null
+++ b/llvm/test/DebugInfo/KeyInstructions/lit.local.cfg
@@ -0,0 +1,2 @@
+if not config.has_key_instructions:
+    config.unsupported = True
diff --git a/llvm/test/lit.site.cfg.py.in b/llvm/test/lit.site.cfg.py.in
index 0d02920323d2d..caee6c1db92ee 100644
--- a/llvm/test/lit.site.cfg.py.in
+++ b/llvm/test/lit.site.cfg.py.in
@@ -65,6 +65,7 @@ config.spirv_tools_tests = @LLVM_INCLUDE_SPIRV_TOOLS_TESTS@
 config.have_vc_rev = @LLVM_APPEND_VC_REV@
 config.force_vc_rev = "@LLVM_FORCE_VC_REVISION@"
 config.has_logf128 = @LLVM_HAS_LOGF128@
+config.has_key_instructions = @LLVM_EXPERIMENTAL_KEY_INSTRUCTIONS@
 
 import lit.llvm
 lit.llvm.initialize(lit_config, config)

>From 42fddab9fe259f7b7286cd49043b80ddf7cf6340 Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Thu, 1 May 2025 13:13:55 +0100
Subject: [PATCH 2/8] nits

---
 llvm/include/llvm/IR/DebugInfoMetadata.h | 7 +++++--
 llvm/lib/AsmParser/LLParser.cpp          | 2 +-
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h
index 03b162737d0a3..91cda271f498b 100644
--- a/llvm/include/llvm/IR/DebugInfoMetadata.h
+++ b/llvm/include/llvm/IR/DebugInfoMetadata.h
@@ -2267,18 +2267,21 @@ class DILocation : public MDNode {
                         getRawInlinedAt(), isImplicitCode(), getAtomGroup(),
                         getAtomRank());
   }
+
 public:
   uint64_t getAtomGroup() const {
 #ifdef EXPERIMENTAL_KEY_INSTRUCTIONS
     return AtomGroup;
-#endif
+#else
     return 0;
+#endif
   }
   uint8_t getAtomRank() const {
 #ifdef EXPERIMENTAL_KEY_INSTRUCTIONS
     return AtomRank;
-#endif
+#else
     return 0;
+#endif
   }
 
   // Disallow replacing operands.
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 0772395e8279b..f40d3c3f56097 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -5319,7 +5319,7 @@ bool LLParser::parseSpecializedMDNode(MDNode *&N, bool IsDistinct) {
 
 /// parseDILocationFields:
 ///   ::= !DILocation(line: 43, column: 8, scope: !5, inlinedAt: !6,
-///   isImplicitCode: true)
+///   isImplicitCode: true, atomGroup: 1, atomRank: 1)
 bool LLParser::parseDILocation(MDNode *&Result, bool IsDistinct) {
 #define VISIT_MD_FIELDS(OPTIONAL, REQUIRED)                                    \
   OPTIONAL(line, LineField, );                                                 \

>From a4e97d1a3911ad57f95a23876ac17fcccf1cd8b8 Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Tue, 18 Mar 2025 16:50:17 +0000
Subject: [PATCH 3/8] [KeyInstr] Add Atom Group waterline to LLVMContext

The waterline is managed through DILocation creation,
LLVMContext::incNextAtomGroup, and LLVMContext::updateAtomGroupWaterline.

Add unittest.
---
 llvm/include/llvm/IR/LLVMContext.h |  8 +++++++
 llvm/lib/IR/DebugInfoMetadata.cpp  |  3 +++
 llvm/lib/IR/LLVMContext.cpp        |  8 +++++++
 llvm/lib/IR/LLVMContextImpl.h      | 10 ++++++++
 llvm/unittests/IR/MetadataTest.cpp | 38 ++++++++++++++++++++++++++++++
 5 files changed, 67 insertions(+)

diff --git a/llvm/include/llvm/IR/LLVMContext.h b/llvm/include/llvm/IR/LLVMContext.h
index bbd125fd38cf1..d3cdd31e0b12f 100644
--- a/llvm/include/llvm/IR/LLVMContext.h
+++ b/llvm/include/llvm/IR/LLVMContext.h
@@ -335,6 +335,14 @@ class LLVMContext {
   StringRef getDefaultTargetFeatures();
   void setDefaultTargetFeatures(StringRef Features);
 
+  /// Key Instructions: update the highest number atom group emitted for any
+  /// function.
+  void updateAtomGroupWaterline(uint64_t G);
+
+  /// Key Instructions: get the next free atom group number and increment
+  /// the global tracker.
+  uint64_t incNextAtomGroup();
+
 private:
   // Module needs access to the add/removeModule methods.
   friend class Module;
diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp
index bfe956d46dd7e..a55b3d832b66e 100644
--- a/llvm/lib/IR/DebugInfoMetadata.cpp
+++ b/llvm/lib/IR/DebugInfoMetadata.cpp
@@ -74,6 +74,9 @@ DILocation::DILocation(LLVMContext &C, StorageType Storage, unsigned Line,
 #ifdef EXPERIMENTAL_KEY_INSTRUCTIONS
   assert(AtomRank <= 7 && "AtomRank number should fit in 3 bits");
 #endif
+  if (AtomRank)
+    C.updateAtomGroupWaterline(AtomGroup + 1);
+
   assert((MDs.size() == 1 || MDs.size() == 2) &&
          "Expected a scope and optional inlined-at");
   // Set line and column.
diff --git a/llvm/lib/IR/LLVMContext.cpp b/llvm/lib/IR/LLVMContext.cpp
index 447e5d92e0b99..4781085b30431 100644
--- a/llvm/lib/IR/LLVMContext.cpp
+++ b/llvm/lib/IR/LLVMContext.cpp
@@ -377,3 +377,11 @@ StringRef LLVMContext::getDefaultTargetFeatures() {
 void LLVMContext::setDefaultTargetFeatures(StringRef Features) {
   pImpl->DefaultTargetFeatures = Features;
 }
+
+void LLVMContext::updateAtomGroupWaterline(uint64_t V) {
+  pImpl->NextAtomGroup = std::max(pImpl->NextAtomGroup, V);
+}
+
+uint64_t LLVMContext::incNextAtomGroup() {
+  return pImpl->NextAtomGroup++;
+}
diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h
index dafb6b8308d77..fc91f36af6169 100644
--- a/llvm/lib/IR/LLVMContextImpl.h
+++ b/llvm/lib/IR/LLVMContextImpl.h
@@ -1858,6 +1858,16 @@ class LLVMContextImpl {
 
   std::string DefaultTargetCPU;
   std::string DefaultTargetFeatures;
+
+  /// The next available source atom group number. The front end is responsible
+  /// for assigning source atom numbers, but certain optimisations need to
+  /// assign new group numbers to a set of instructions. Most often code
+  /// duplication optimisations like loop unroll. Tracking a global maximum
+  /// value means we can know (cheaply) we're never using a group number that's
+  /// already used within this function.
+  ///
+  /// Start a 1 because 0 means the source location isn't part of an atom group.
+  uint64_t NextAtomGroup = 1;
 };
 
 } // end namespace llvm
diff --git a/llvm/unittests/IR/MetadataTest.cpp b/llvm/unittests/IR/MetadataTest.cpp
index e710f7845df5e..d072e1119b490 100644
--- a/llvm/unittests/IR/MetadataTest.cpp
+++ b/llvm/unittests/IR/MetadataTest.cpp
@@ -6,6 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "../lib/IR/LLVMContextImpl.h"
 #include "llvm/IR/Metadata.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/STLExtras.h"
@@ -1568,6 +1569,43 @@ TEST_F(DILocationTest, discriminatorSpecialCases) {
   EXPECT_EQ(std::nullopt, L4->cloneByMultiplyingDuplicationFactor(0x1000));
 }
 
+TEST_F(DILocationTest, KeyInstructions) {
+  Context.pImpl->NextAtomGroup = 1;
+
+  EXPECT_EQ(Context.pImpl->NextAtomGroup, 1u);
+  DILocation *A1 = DILocation::get(Context, 1, 0, getSubprogram(), nullptr, false, 1, 2);
+  // The group is only applied to the DILocation if the build has opted into
+  // the additional DILocation fields needed for the feature.
+#ifdef EXPERIMENTAL_KEY_INSTRUCTIONS
+  EXPECT_EQ(A1->getAtomGroup(), 1u);
+  EXPECT_EQ(A1->getAtomRank(), 2u);
+#else
+  EXPECT_EQ(A1->getAtomGroup(), 0u);
+  EXPECT_EQ(A1->getAtomRank(), 0u);
+#endif
+
+  // Group number 1 has been "used" so next available is 2.
+  EXPECT_EQ(Context.pImpl->NextAtomGroup, 2u);
+
+  // Set a group number higher than current + 1, then check the waterline.
+  DILocation::get(Context, 2, 0, getSubprogram(), nullptr, false, 5, 1);
+  EXPECT_EQ(Context.pImpl->NextAtomGroup, 6u);
+
+  // The waterline should be unchanged (group <= next).
+  DILocation::get(Context, 3, 0, getSubprogram(), nullptr, false, 4, 1);
+  EXPECT_EQ(Context.pImpl->NextAtomGroup, 6u);
+  DILocation::get(Context, 3, 0, getSubprogram(), nullptr, false, 5, 1);
+  EXPECT_EQ(Context.pImpl->NextAtomGroup, 6u);
+
+  // Check the waterline gets incremented by 1.
+  EXPECT_EQ(Context.incNextAtomGroup(), 6u);
+  EXPECT_EQ(Context.pImpl->NextAtomGroup, 7u);
+
+  Context.updateAtomGroupWaterline(8);
+  EXPECT_EQ(Context.pImpl->NextAtomGroup, 8u);
+  Context.updateAtomGroupWaterline(7);
+  EXPECT_EQ(Context.pImpl->NextAtomGroup, 8u);
+}
 
 typedef MetadataTest GenericDINodeTest;
 

>From 8fc47cb54f5062988a1f6817af08d16325324335 Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Thu, 1 May 2025 13:19:36 +0100
Subject: [PATCH 4/8] clang-format

---
 llvm/lib/IR/LLVMContext.cpp        | 4 +---
 llvm/unittests/IR/MetadataTest.cpp | 5 +++--
 2 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/llvm/lib/IR/LLVMContext.cpp b/llvm/lib/IR/LLVMContext.cpp
index 4781085b30431..5a11c28671409 100644
--- a/llvm/lib/IR/LLVMContext.cpp
+++ b/llvm/lib/IR/LLVMContext.cpp
@@ -382,6 +382,4 @@ void LLVMContext::updateAtomGroupWaterline(uint64_t V) {
   pImpl->NextAtomGroup = std::max(pImpl->NextAtomGroup, V);
 }
 
-uint64_t LLVMContext::incNextAtomGroup() {
-  return pImpl->NextAtomGroup++;
-}
+uint64_t LLVMContext::incNextAtomGroup() { return pImpl->NextAtomGroup++; }
diff --git a/llvm/unittests/IR/MetadataTest.cpp b/llvm/unittests/IR/MetadataTest.cpp
index d072e1119b490..2b852eff6b240 100644
--- a/llvm/unittests/IR/MetadataTest.cpp
+++ b/llvm/unittests/IR/MetadataTest.cpp
@@ -6,8 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "../lib/IR/LLVMContextImpl.h"
 #include "llvm/IR/Metadata.h"
+#include "../lib/IR/LLVMContextImpl.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/IR/Constants.h"
@@ -1573,7 +1573,8 @@ TEST_F(DILocationTest, KeyInstructions) {
   Context.pImpl->NextAtomGroup = 1;
 
   EXPECT_EQ(Context.pImpl->NextAtomGroup, 1u);
-  DILocation *A1 = DILocation::get(Context, 1, 0, getSubprogram(), nullptr, false, 1, 2);
+  DILocation *A1 =
+      DILocation::get(Context, 1, 0, getSubprogram(), nullptr, false, 1, 2);
   // The group is only applied to the DILocation if the build has opted into
   // the additional DILocation fields needed for the feature.
 #ifdef EXPERIMENTAL_KEY_INSTRUCTIONS

>From 4e82b35aaece4f1870fd28483ce012a653bf5756 Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Thu, 1 May 2025 13:40:03 +0100
Subject: [PATCH 5/8] rename functions

---
 llvm/include/llvm/IR/LLVMContext.h | 4 ++--
 llvm/lib/IR/DebugInfoMetadata.cpp  | 2 +-
 llvm/lib/IR/LLVMContext.cpp        | 6 ++++--
 3 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/llvm/include/llvm/IR/LLVMContext.h b/llvm/include/llvm/IR/LLVMContext.h
index d3cdd31e0b12f..6dde7a968b570 100644
--- a/llvm/include/llvm/IR/LLVMContext.h
+++ b/llvm/include/llvm/IR/LLVMContext.h
@@ -337,11 +337,11 @@ class LLVMContext {
 
   /// Key Instructions: update the highest number atom group emitted for any
   /// function.
-  void updateAtomGroupWaterline(uint64_t G);
+  void updateDILocationAtomGroupWaterline(uint64_t G);
 
   /// Key Instructions: get the next free atom group number and increment
   /// the global tracker.
-  uint64_t incNextAtomGroup();
+  uint64_t incNextDILocationAtomGroup();
 
 private:
   // Module needs access to the add/removeModule methods.
diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp
index a55b3d832b66e..e32b6e2875245 100644
--- a/llvm/lib/IR/DebugInfoMetadata.cpp
+++ b/llvm/lib/IR/DebugInfoMetadata.cpp
@@ -75,7 +75,7 @@ DILocation::DILocation(LLVMContext &C, StorageType Storage, unsigned Line,
   assert(AtomRank <= 7 && "AtomRank number should fit in 3 bits");
 #endif
   if (AtomRank)
-    C.updateAtomGroupWaterline(AtomGroup + 1);
+    C.updateDILocationAtomGroupWaterline(AtomGroup + 1);
 
   assert((MDs.size() == 1 || MDs.size() == 2) &&
          "Expected a scope and optional inlined-at");
diff --git a/llvm/lib/IR/LLVMContext.cpp b/llvm/lib/IR/LLVMContext.cpp
index 5a11c28671409..57532cd491dd6 100644
--- a/llvm/lib/IR/LLVMContext.cpp
+++ b/llvm/lib/IR/LLVMContext.cpp
@@ -378,8 +378,10 @@ void LLVMContext::setDefaultTargetFeatures(StringRef Features) {
   pImpl->DefaultTargetFeatures = Features;
 }
 
-void LLVMContext::updateAtomGroupWaterline(uint64_t V) {
+void LLVMContext::updateDILocationAtomGroupWaterline(uint64_t V) {
   pImpl->NextAtomGroup = std::max(pImpl->NextAtomGroup, V);
 }
 
-uint64_t LLVMContext::incNextAtomGroup() { return pImpl->NextAtomGroup++; }
+uint64_t LLVMContext::incNextDILocationAtomGroup() {
+  return pImpl->NextAtomGroup++;
+}

>From 372485e595f2ed2157cce1ac0d6bbb23ca060b34 Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Thu, 1 May 2025 13:41:48 +0100
Subject: [PATCH 6/8] fix my fixme comment

---
 llvm/lib/IR/DebugInfoMetadata.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp
index e32b6e2875245..e3b105a6ac109 100644
--- a/llvm/lib/IR/DebugInfoMetadata.cpp
+++ b/llvm/lib/IR/DebugInfoMetadata.cpp
@@ -74,7 +74,7 @@ DILocation::DILocation(LLVMContext &C, StorageType Storage, unsigned Line,
 #ifdef EXPERIMENTAL_KEY_INSTRUCTIONS
   assert(AtomRank <= 7 && "AtomRank number should fit in 3 bits");
 #endif
-  if (AtomRank)
+  if (AtomGroup)
     C.updateDILocationAtomGroupWaterline(AtomGroup + 1);
 
   assert((MDs.size() == 1 || MDs.size() == 2) &&

>From c9c9826050d3fb05edf0ca06e2612158d9a288ac Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Thu, 1 May 2025 13:46:57 +0100
Subject: [PATCH 7/8] simplify comment

---
 llvm/unittests/IR/MetadataTest.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/unittests/IR/MetadataTest.cpp b/llvm/unittests/IR/MetadataTest.cpp
index 2b852eff6b240..b1a7d9966ffc4 100644
--- a/llvm/unittests/IR/MetadataTest.cpp
+++ b/llvm/unittests/IR/MetadataTest.cpp
@@ -1575,8 +1575,8 @@ TEST_F(DILocationTest, KeyInstructions) {
   EXPECT_EQ(Context.pImpl->NextAtomGroup, 1u);
   DILocation *A1 =
       DILocation::get(Context, 1, 0, getSubprogram(), nullptr, false, 1, 2);
-  // The group is only applied to the DILocation if the build has opted into
-  // the additional DILocation fields needed for the feature.
+  // The group is only applied to the DILocation if we've built LLVM with
+  // EXPERIMENTAL_KEY_INSTRUCTIONS.
 #ifdef EXPERIMENTAL_KEY_INSTRUCTIONS
   EXPECT_EQ(A1->getAtomGroup(), 1u);
   EXPECT_EQ(A1->getAtomRank(), 2u);

>From 47e9f41d2c9903c71355372e45660734b1c8294d Mon Sep 17 00:00:00 2001
From: Orlando Cazalet-Hyams <orlando.hyams at sony.com>
Date: Thu, 1 May 2025 14:37:38 +0100
Subject: [PATCH 8/8] update function names in unittests too

---
 llvm/unittests/IR/MetadataTest.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/llvm/unittests/IR/MetadataTest.cpp b/llvm/unittests/IR/MetadataTest.cpp
index b1a7d9966ffc4..40f91ff5386b2 100644
--- a/llvm/unittests/IR/MetadataTest.cpp
+++ b/llvm/unittests/IR/MetadataTest.cpp
@@ -1599,12 +1599,12 @@ TEST_F(DILocationTest, KeyInstructions) {
   EXPECT_EQ(Context.pImpl->NextAtomGroup, 6u);
 
   // Check the waterline gets incremented by 1.
-  EXPECT_EQ(Context.incNextAtomGroup(), 6u);
+  EXPECT_EQ(Context.incNextDILocationAtomGroup(), 6u);
   EXPECT_EQ(Context.pImpl->NextAtomGroup, 7u);
 
-  Context.updateAtomGroupWaterline(8);
+  Context.updateDILocationAtomGroupWaterline(8);
   EXPECT_EQ(Context.pImpl->NextAtomGroup, 8u);
-  Context.updateAtomGroupWaterline(7);
+  Context.updateDILocationAtomGroupWaterline(7);
   EXPECT_EQ(Context.pImpl->NextAtomGroup, 8u);
 }
 



More information about the llvm-commits mailing list