[llvm-branch-commits] [llvm] [KeyInstr] Merge atoms in DILocation::getMergedLocation (PR #133480)

Jeremy Morse via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Fri Apr 11 01:49:31 PDT 2025


================
@@ -1243,6 +1243,140 @@ TEST_F(DILocationTest, Merge) {
     auto *M2 = DILocation::getMergedLocation(A2, B);
     EXPECT_EQ(M1, M2);
   }
+
+#ifdef EXPERIMENTAL_KEY_INSTRUCTIONS
+#define EXPECT_ATOM(Loc, Group, Rank)                                          \
+  EXPECT_EQ(Group, M->getAtomGroup());                                         \
+  EXPECT_EQ(Rank, M->getAtomRank());
+#else
+#define EXPECT_ATOM(Loc, Group, Rank)                                          \
+  EXPECT_EQ(0u, M->getAtomGroup());                                            \
+  EXPECT_EQ(0u, M->getAtomRank());                                             \
+  (void)Group;                                                                 \
+  (void)Rank;
+#endif
+  // Identical, including source atom numbers.
+  {
+    auto *A = DILocation::get(Context, 2, 7, N, nullptr, false, 1, 1);
+    auto *B = DILocation::get(Context, 2, 7, N, nullptr, false, 1, 1);
+    auto *M = DILocation::getMergedLocation(A, B);
+    EXPECT_ATOM(M, 1u, 1u);
+    // DILocations are uniqued, so we can check equality by ptr.
+    EXPECT_EQ(M, DILocation::getMergedLocation(A, B));
+  }
+
+  // Identical but different atom ranks (same atom) - choose the lowest nonzero
+  // rank.
+  {
+    auto *A = DILocation::get(Context, 2, 7, N, nullptr, false, 1, 1);
+    auto *B = DILocation::get(Context, 2, 7, N, nullptr, false, 1, 2);
+    auto *M = DILocation::getMergedLocation(A, B);
+    EXPECT_ATOM(M, 1u, 1u);
+    EXPECT_EQ(M, DILocation::getMergedLocation(B, A));
+
+    A = DILocation::get(Context, 2, 7, N, nullptr, false, 1, 0);
+    B = DILocation::get(Context, 2, 7, N, nullptr, false, 1, 2);
+    M = DILocation::getMergedLocation(A, B);
+    EXPECT_ATOM(M, 1u, 2u);
+    EXPECT_EQ(M, DILocation::getMergedLocation(B, A));
+  }
+
+  // Identical but different atom ranks (different atom) - choose the lowest
+  // nonzero rank.
+  {
+    auto *A = DILocation::get(Context, 2, 7, N, nullptr, false, 1, 1);
+    auto *B = DILocation::get(Context, 2, 7, N, nullptr, false, 2, 2);
+    auto *M = DILocation::getMergedLocation(A, B);
+    EXPECT_ATOM(M, 1u, 1u);
+    EXPECT_EQ(M, DILocation::getMergedLocation(B, A));
+
+    A = DILocation::get(Context, 2, 7, N, nullptr, false, 1, 0);
+    B = DILocation::get(Context, 2, 7, N, nullptr, false, 2, 2);
+    M = DILocation::getMergedLocation(A, B);
+    EXPECT_ATOM(M, 2u, 2u);
+    EXPECT_EQ(M, DILocation::getMergedLocation(B, A));
+  }
+
+  // Identical but equal atom rank (different atom) - choose the lowest non-zero
+  // group (arbitrary choice for deterministic behaviour).
+  {
+    auto *A = DILocation::get(Context, 2, 7, N, nullptr, false, 1, 1);
+    auto *B = DILocation::get(Context, 2, 7, N, nullptr, false, 2, 1);
+    auto *M = DILocation::getMergedLocation(A, B);
+    EXPECT_ATOM(M, 1u, 1u);
+    EXPECT_EQ(M, DILocation::getMergedLocation(B, A));
+
+    A = DILocation::get(Context, 2, 7, N, nullptr, false, 0, 1);
+    B = DILocation::get(Context, 2, 7, N, nullptr, false, 2, 1);
+    M = DILocation::getMergedLocation(A, B);
+    EXPECT_ATOM(M, 2u, 1u);
+    EXPECT_EQ(M, DILocation::getMergedLocation(B, A));
+  }
+
+  // Completely different except same atom numbers. Zero out the atoms.
+  {
+    auto *I = DILocation::get(Context, 2, 7, N);
+    auto *A = DILocation::get(Context, 1, 6, S, I, false, 1, 1);
+    auto *B =
+        DILocation::get(Context, 2, 7, getSubprogram(), nullptr, false, 1, 1);
+    auto *M = DILocation::getMergedLocation(A, B);
+    EXPECT_EQ(0u, M->getLine());
+    EXPECT_EQ(0u, M->getColumn());
+    EXPECT_TRUE(isa<DILocalScope>(M->getScope()));
+    EXPECT_EQ(S, M->getScope());
+    EXPECT_EQ(nullptr, M->getInlinedAt());
+  }
+
+  // Same inlined-at chain but different atoms. Choose the lowest
+  // non-zero group (arbitrary choice for deterministic behaviour).
+  {
+    auto *I = DILocation::get(Context, 1, 7, N);
+    auto *F = getSubprogram();
+    auto *A = DILocation::get(Context, 1, 1, F, I, false, 1, 2);
+    auto *B = DILocation::get(Context, 1, 1, F, I, false, 2, 1);
+    auto *M = DILocation::getMergedLocation(A, B);
+    EXPECT_ATOM(M, 2u, 1u);
+    EXPECT_EQ(M, DILocation::getMergedLocation(B, A));
+
+    A = DILocation::get(Context, 1, 1, F, I, false, 1, 2);
+    B = DILocation::get(Context, 1, 1, F, I, false, 2, 0);
+    M = DILocation::getMergedLocation(A, B);
+    EXPECT_ATOM(M, 1u, 2u);
+    EXPECT_EQ(M, DILocation::getMergedLocation(B, A));
+  }
+
+  // Partially equal inlined-at chain but different atoms. Generate a new atom
+  // group (if either have a group number). This configuration seems unlikely
+  // to occur as line numbers must match, but isn't impossible.
+  {
----------------
jmorse wrote:

I believe it's a desired and supported configuration for this to occur when a function is inlined multiple times then the copies are merged: we keep the line number of the instruction, but put line-zero in the inlinedAt field so that the inlining-callstack refers to a nonexistant location. Thus, we're saying "It's definitely this line, but we can't tell you what inlining context it came from, there were a few".

I don't know whether it makes sense to try and support key instructions in that situation; I feel that falling back to old stepping behaviour is fine in these rare circumstances.

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


More information about the llvm-branch-commits mailing list