Skip to content

Commit 43a9d5d

Browse files
authored
[KeyInstr] Add Atom Group waterline to LLVMContext (#133478)
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
1 parent 0159a26 commit 43a9d5d

File tree

5 files changed

+68
-0
lines changed

5 files changed

+68
-0
lines changed

llvm/include/llvm/IR/LLVMContext.h

+8
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,14 @@ class LLVMContext {
335335
StringRef getDefaultTargetFeatures();
336336
void setDefaultTargetFeatures(StringRef Features);
337337

338+
/// Key Instructions: update the highest number atom group emitted for any
339+
/// function.
340+
void updateDILocationAtomGroupWaterline(uint64_t G);
341+
342+
/// Key Instructions: get the next free atom group number and increment
343+
/// the global tracker.
344+
uint64_t incNextDILocationAtomGroup();
345+
338346
private:
339347
// Module needs access to the add/removeModule methods.
340348
friend class Module;

llvm/lib/IR/DebugInfoMetadata.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ DILocation::DILocation(LLVMContext &C, StorageType Storage, unsigned Line,
7474
#ifdef EXPERIMENTAL_KEY_INSTRUCTIONS
7575
assert(AtomRank <= 7 && "AtomRank number should fit in 3 bits");
7676
#endif
77+
if (AtomGroup)
78+
C.updateDILocationAtomGroupWaterline(AtomGroup + 1);
79+
7780
assert((MDs.size() == 1 || MDs.size() == 2) &&
7881
"Expected a scope and optional inlined-at");
7982
// Set line and column.

llvm/lib/IR/LLVMContext.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -377,3 +377,11 @@ StringRef LLVMContext::getDefaultTargetFeatures() {
377377
void LLVMContext::setDefaultTargetFeatures(StringRef Features) {
378378
pImpl->DefaultTargetFeatures = Features;
379379
}
380+
381+
void LLVMContext::updateDILocationAtomGroupWaterline(uint64_t V) {
382+
pImpl->NextAtomGroup = std::max(pImpl->NextAtomGroup, V);
383+
}
384+
385+
uint64_t LLVMContext::incNextDILocationAtomGroup() {
386+
return pImpl->NextAtomGroup++;
387+
}

llvm/lib/IR/LLVMContextImpl.h

+10
Original file line numberDiff line numberDiff line change
@@ -1880,6 +1880,16 @@ class LLVMContextImpl {
18801880

18811881
std::string DefaultTargetCPU;
18821882
std::string DefaultTargetFeatures;
1883+
1884+
/// The next available source atom group number. The front end is responsible
1885+
/// for assigning source atom numbers, but certain optimisations need to
1886+
/// assign new group numbers to a set of instructions. Most often code
1887+
/// duplication optimisations like loop unroll. Tracking a global maximum
1888+
/// value means we can know (cheaply) we're never using a group number that's
1889+
/// already used within this function.
1890+
///
1891+
/// Start a 1 because 0 means the source location isn't part of an atom group.
1892+
uint64_t NextAtomGroup = 1;
18831893
};
18841894

18851895
} // end namespace llvm

llvm/unittests/IR/MetadataTest.cpp

+39
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "llvm/IR/Metadata.h"
10+
#include "../lib/IR/LLVMContextImpl.h"
1011
#include "llvm/ADT/DenseMap.h"
1112
#include "llvm/ADT/STLExtras.h"
1213
#include "llvm/IR/Constants.h"
@@ -1591,6 +1592,44 @@ TEST_F(DILocationTest, discriminatorSpecialCases) {
15911592
EXPECT_EQ(std::nullopt, L4->cloneByMultiplyingDuplicationFactor(0x1000));
15921593
}
15931594

1595+
TEST_F(DILocationTest, KeyInstructions) {
1596+
Context.pImpl->NextAtomGroup = 1;
1597+
1598+
EXPECT_EQ(Context.pImpl->NextAtomGroup, 1u);
1599+
DILocation *A1 =
1600+
DILocation::get(Context, 1, 0, getSubprogram(), nullptr, false, 1, 2);
1601+
// The group is only applied to the DILocation if we've built LLVM with
1602+
// EXPERIMENTAL_KEY_INSTRUCTIONS.
1603+
#ifdef EXPERIMENTAL_KEY_INSTRUCTIONS
1604+
EXPECT_EQ(A1->getAtomGroup(), 1u);
1605+
EXPECT_EQ(A1->getAtomRank(), 2u);
1606+
#else
1607+
EXPECT_EQ(A1->getAtomGroup(), 0u);
1608+
EXPECT_EQ(A1->getAtomRank(), 0u);
1609+
#endif
1610+
1611+
// Group number 1 has been "used" so next available is 2.
1612+
EXPECT_EQ(Context.pImpl->NextAtomGroup, 2u);
1613+
1614+
// Set a group number higher than current + 1, then check the waterline.
1615+
DILocation::get(Context, 2, 0, getSubprogram(), nullptr, false, 5, 1);
1616+
EXPECT_EQ(Context.pImpl->NextAtomGroup, 6u);
1617+
1618+
// The waterline should be unchanged (group <= next).
1619+
DILocation::get(Context, 3, 0, getSubprogram(), nullptr, false, 4, 1);
1620+
EXPECT_EQ(Context.pImpl->NextAtomGroup, 6u);
1621+
DILocation::get(Context, 3, 0, getSubprogram(), nullptr, false, 5, 1);
1622+
EXPECT_EQ(Context.pImpl->NextAtomGroup, 6u);
1623+
1624+
// Check the waterline gets incremented by 1.
1625+
EXPECT_EQ(Context.incNextDILocationAtomGroup(), 6u);
1626+
EXPECT_EQ(Context.pImpl->NextAtomGroup, 7u);
1627+
1628+
Context.updateDILocationAtomGroupWaterline(8);
1629+
EXPECT_EQ(Context.pImpl->NextAtomGroup, 8u);
1630+
Context.updateDILocationAtomGroupWaterline(7);
1631+
EXPECT_EQ(Context.pImpl->NextAtomGroup, 8u);
1632+
}
15941633

15951634
typedef MetadataTest GenericDINodeTest;
15961635

0 commit comments

Comments
 (0)