Skip to content

[KeyInstr] Add Atom Group waterline to LLVMContext #133478

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
May 6, 2025

Conversation

OCHyams
Copy link
Contributor

@OCHyams OCHyams commented Mar 28, 2025

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

Add unittest.

Copy link
Contributor Author

OCHyams commented Mar 28, 2025

This stack of pull requests is managed by Graphite. Learn more about stacking.

Copy link

github-actions bot commented Mar 28, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@llvmbot
Copy link
Member

llvmbot commented Mar 28, 2025

@llvm/pr-subscribers-llvm-ir

@llvm/pr-subscribers-debuginfo

Author: Orlando Cazalet-Hyams (OCHyams)

Changes

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

Add unittest.


Full diff: https://github.com/llvm/llvm-project/pull/133478.diff

5 Files Affected:

  • (modified) llvm/include/llvm/IR/LLVMContext.h (+8)
  • (modified) llvm/lib/IR/DebugInfoMetadata.cpp (+3)
  • (modified) llvm/lib/IR/LLVMContext.cpp (+8)
  • (modified) llvm/lib/IR/LLVMContextImpl.h (+10)
  • (modified) llvm/unittests/IR/MetadataTest.cpp (+38)
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 f4f9fca38945c..aefda2f7be0b0 100644
--- a/llvm/lib/IR/DebugInfoMetadata.cpp
+++ b/llvm/lib/IR/DebugInfoMetadata.cpp
@@ -67,6 +67,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 99f0d8837de52..5a52d41834095 100644
--- a/llvm/lib/IR/LLVMContextImpl.h
+++ b/llvm/lib/IR/LLVMContextImpl.h
@@ -1832,6 +1832,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 94cebb0406598..8a1c1f9d306c6 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"
@@ -1366,6 +1367,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;
 

@OCHyams OCHyams force-pushed the users/OCHyams/ki-llvm-waterline branch from 9c1e61e to c9c9826 Compare May 1, 2025 13:28
@OCHyams OCHyams force-pushed the users/OCHyams/ki-llvm-fields branch from 70b9bbe to 42fddab Compare May 1, 2025 13:30
Base automatically changed from users/OCHyams/ki-llvm-fields to main May 1, 2025 14:40
OCHyams added 6 commits May 6, 2025 10:32
The waterline is managed through DILocation creation,
LLVMContext::incNextAtomGroup, and LLVMContext::updateAtomGroupWaterline.

Add unittest.
@OCHyams OCHyams force-pushed the users/OCHyams/ki-llvm-waterline branch from 47e9f41 to 93fa11d Compare May 6, 2025 09:33
@OCHyams OCHyams merged commit 43a9d5d into main May 6, 2025
8 of 10 checks passed
@OCHyams OCHyams deleted the users/OCHyams/ki-llvm-waterline branch May 6, 2025 10:42
OCHyams added a commit to OCHyams/llvm-project that referenced this pull request May 6, 2025
Source location atoms are identified by a function-local number and the
DILocation's InlinedAt field. The front end is responsible for assigning source
atom numbers, but certain optimisations need to assign new atom numbers to some
instructions. Most often code duplication optimisations like loop
unroll. Tracking a global maximum value (waterline) means we can easily
(cheaply) get new numbers that don't clash in any function.

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

Add unittest.

RFC:
https://discourse.llvm.org/t/rfc-improving-is-stmt-placement-for-better-interactive-debugging/82668
OCHyams added a commit to OCHyams/llvm-project that referenced this pull request May 6, 2025
Source location atoms are identified by a function-local number and the
DILocation's InlinedAt field. The front end is responsible for assigning source
atom numbers, but certain optimisations need to assign new atom numbers to some
instructions. Most often code duplication optimisations like loop
unroll. Tracking a global maximum value (waterline) means we can easily
(cheaply) get new numbers that don't clash in any function.

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

Add unittest.

RFC:
https://discourse.llvm.org/t/rfc-improving-is-stmt-placement-for-better-interactive-debugging/82668
GeorgeARM pushed a commit to GeorgeARM/llvm-project that referenced this pull request May 7, 2025
Source location atoms are identified by a function-local number and the
DILocation's InlinedAt field. The front end is responsible for assigning source
atom numbers, but certain optimisations need to assign new atom numbers to some
instructions. Most often code duplication optimisations like loop
unroll. Tracking a global maximum value (waterline) means we can easily
(cheaply) get new numbers that don't clash in any function.

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

Add unittest.

RFC:
https://discourse.llvm.org/t/rfc-improving-is-stmt-placement-for-better-interactive-debugging/82668
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants