[llvm] [NVPTX] Drop cache hints on volatile loads/stores (PR #214830)
Yonah Goldberg via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 7 11:55:20 PDT 2026
https://github.com/YonahGoldberg created https://github.com/llvm/llvm-project/pull/214830
https://github.com/llvm/llvm-project/pull/204067 added cache hint metadata support for NVPTX. I forgot to handle volatile loads/stores correctly. Volatile loads only support .level::prefetch_size and volatile stores don't support any cache hints. This PR drops unsupported metadata for volatile loads/stores.
>From 34e28b6fba1f2e02df6d6dd47a9427d94282407f Mon Sep 17 00:00:00 2001
From: Yonah Goldberg <ygoldberg at nvidia.com>
Date: Fri, 7 Aug 2026 18:51:38 +0000
Subject: [PATCH 1/2] fix
---
llvm/lib/Target/NVPTX/NVPTXISelDAGToDAG.cpp | 15 +++++------
.../CodeGen/NVPTX/cache-hint-load-store.ll | 25 +++++++++++++++++++
2 files changed, 33 insertions(+), 7 deletions(-)
diff --git a/llvm/lib/Target/NVPTX/NVPTXISelDAGToDAG.cpp b/llvm/lib/Target/NVPTX/NVPTXISelDAGToDAG.cpp
index f3db3c354c290..762c0fead6822 100644
--- a/llvm/lib/Target/NVPTX/NVPTXISelDAGToDAG.cpp
+++ b/llvm/lib/Target/NVPTX/NVPTXISelDAGToDAG.cpp
@@ -77,6 +77,7 @@ struct NVPTXMemCacheHintAccess {
bool IsLoad;
unsigned NumElts;
unsigned EltWidth;
+ bool IsVolatile;
};
class NVPTXDAGToDAGISel : public SelectionDAGISel {
@@ -1220,7 +1221,7 @@ static bool isL2EvictionSupported(const NVPTXSubtarget &Subtarget,
if (Eviction == NVPTX::L2Eviction::Normal)
return true;
- return Subtarget.hasL2EvictionHint() && isGlobalOrGeneric(Access.AddrSpace) &&
+ return Subtarget.hasL2EvictionHint() && isGlobalOrGeneric(Access.AddrSpace) && !Access.IsVolatile &&
((Access.NumElts == 8 && Access.EltWidth == 32) ||
(Access.NumElts == 4 && Access.EltWidth == 64));
}
@@ -1250,7 +1251,7 @@ std::pair<unsigned, SDValue> NVPTXDAGToDAGISel::getMemCacheHintOperands(
if (KeyStr == "nvvm.l1_eviction") {
auto ParsedL1 =
parseMemCacheHintStringValue(Ctx, KeyStr, Value, parseL1Eviction);
- if (ParsedL1 && Subtarget->hasL1EvictionHint())
+ if (ParsedL1 && !Access.IsVolatile && Subtarget->hasL1EvictionHint())
L1 = *ParsedL1;
continue;
}
@@ -1277,7 +1278,7 @@ std::pair<unsigned, SDValue> NVPTXDAGToDAGISel::getMemCacheHintOperands(
if (!ValCI)
emitInvalidMemCacheHint(
Ctx, "'nvvm.l2_cache_hint' expects an integer value");
- else if (isGlobalOrGeneric(Access.AddrSpace) &&
+ else if (isGlobalOrGeneric(Access.AddrSpace) && !Access.IsVolatile &&
Subtarget->hasL2CacheHint())
CachePolicy = ValCI->getZExtValue();
continue;
@@ -1344,7 +1345,7 @@ bool NVPTXDAGToDAGISel::tryLoad(SDNode *N) {
const auto [EvictionAndPrefetchHint, PolicyReg] =
getMemCacheHintOperands(LD,
{CodeAddrSpace, /*IsLoad=*/true,
- /*NumElts=*/1, /*EltWidth=*/FromTypeWidth},
+ /*NumElts=*/1, /*EltWidth=*/FromTypeWidth, LD->isVolatile()},
DL);
// Create the machine instruction DAG
@@ -1493,7 +1494,7 @@ bool NVPTXDAGToDAGISel::tryLDG(MemSDNode *LD) {
const auto [EvictionAndPrefetchHint, PolicyReg] = getMemCacheHintOperands(
LD,
{NVPTX::AddressSpace::Global,
- /*IsLoad=*/true, LD->getNumValues() - 1, FromTypeWidth},
+ /*IsLoad=*/true, LD->getNumValues() - 1, FromTypeWidth, LD->isVolatile()},
DL);
SDValue Ops[] = {getI32Imm(FromType, DL),
getI32Imm(FromTypeWidth, DL),
@@ -1615,7 +1616,7 @@ bool NVPTXDAGToDAGISel::tryStore(SDNode *N) {
const auto [EvictionAndPrefetchHint, PolicyReg] =
getMemCacheHintOperands(ST,
{CodeAddrSpace, /*IsLoad=*/false,
- /*NumElts=*/1, /*EltWidth=*/ToTypeWidth},
+ /*NumElts=*/1, /*EltWidth=*/ToTypeWidth, ST->isVolatile()},
DL);
SDValue Ops[] = {selectPossiblyImm(Value),
@@ -1676,7 +1677,7 @@ bool NVPTXDAGToDAGISel::tryStoreVector(SDNode *N) {
const auto [EvictionAndPrefetchHint, PolicyReg] = getMemCacheHintOperands(
ST,
{CodeAddrSpace, /*IsLoad=*/false, /*NumElts=*/NumElts,
- /*EltWidth=*/ToTypeWidth},
+ /*EltWidth=*/ToTypeWidth, ST->isVolatile()},
DL);
const auto [Base, Offset] = selectADDR(Addr, CurDAG);
diff --git a/llvm/test/CodeGen/NVPTX/cache-hint-load-store.ll b/llvm/test/CodeGen/NVPTX/cache-hint-load-store.ll
index 8680ae5c6a180..322e538170d84 100644
--- a/llvm/test/CodeGen/NVPTX/cache-hint-load-store.ll
+++ b/llvm/test/CodeGen/NVPTX/cache-hint-load-store.ll
@@ -362,6 +362,28 @@ define void @test_store_no_hint(ptr addrspace(1) %p, i32 %v) {
ret void
}
+;-----------------------------------------------------------------------------
+; Volatile loads and stores
+;-----------------------------------------------------------------------------
+
+; Volatile load with l1 + l2 eviction, l2 prefetch, and l2 cache hint. Volatile
+; loads only support l2 prefetch, so the rest should be dropped.
+define i32 @test_volatile_load_drop_hint(ptr addrspace(1) %p) {
+; CHECK-LABEL: test_volatile_load_drop_hint(
+; CHECK: ld.volatile.global.L2::128B.b32 %r1, [%rd1];
+ %v = load volatile i32, ptr addrspace(1) %p, !mem.cache_hint !100
+ ret i32 %v
+}
+
+; Volatile store with l1 + l2 eviction, l2 prefetch, and l2 cache hint. Volatile
+; stores don't support any of these, so they should all be dropped.
+define void @test_volatile_store_drop_hint(ptr addrspace(1) %p, i32 %v) {
+; CHECK-LABEL: test_volatile_store_drop_hint(
+; CHECK: st.volatile.global.b32 [%rd1], %r1;
+ store volatile i32 %v, ptr addrspace(1) %p, !mem.cache_hint !101
+ ret void
+}
+
;-----------------------------------------------------------------------------
; Metadata definitions
;-----------------------------------------------------------------------------
@@ -406,3 +428,6 @@ define void @test_store_no_hint(ptr addrspace(1) %p, i32 %v) {
!23 = !{i32 1, !37}
!24 = !{i32 0, !39}
!39 = !{!"nvvm.l2_cache_hint", i64 12345}
+!100 = !{i32 0, !102}
+!101 = !{i32 1, !102}
+!102 = !{!"nvvm.l1_eviction", !"first", !"nvvm.l2_eviction", !"last", !"nvvm.l2_prefetch_size", !"128B", !"nvvm.l2_cache_hint", i64 12345}
>From c04c82fae6676d169d85e85ebd663da5f6066b51 Mon Sep 17 00:00:00 2001
From: Yonah Goldberg <ygoldberg at nvidia.com>
Date: Fri, 7 Aug 2026 18:51:54 +0000
Subject: [PATCH 2/2] format
---
llvm/lib/Target/NVPTX/NVPTXISelDAGToDAG.cpp | 34 +++++++++++----------
1 file changed, 18 insertions(+), 16 deletions(-)
diff --git a/llvm/lib/Target/NVPTX/NVPTXISelDAGToDAG.cpp b/llvm/lib/Target/NVPTX/NVPTXISelDAGToDAG.cpp
index 762c0fead6822..9f69af82c1b13 100644
--- a/llvm/lib/Target/NVPTX/NVPTXISelDAGToDAG.cpp
+++ b/llvm/lib/Target/NVPTX/NVPTXISelDAGToDAG.cpp
@@ -1221,7 +1221,8 @@ static bool isL2EvictionSupported(const NVPTXSubtarget &Subtarget,
if (Eviction == NVPTX::L2Eviction::Normal)
return true;
- return Subtarget.hasL2EvictionHint() && isGlobalOrGeneric(Access.AddrSpace) && !Access.IsVolatile &&
+ return Subtarget.hasL2EvictionHint() && isGlobalOrGeneric(Access.AddrSpace) &&
+ !Access.IsVolatile &&
((Access.NumElts == 8 && Access.EltWidth == 32) ||
(Access.NumElts == 4 && Access.EltWidth == 64));
}
@@ -1342,11 +1343,11 @@ bool NVPTXDAGToDAGISel::tryLoad(SDNode *N) {
FromTypeWidth <= 128 && "Invalid width for load");
const auto [Base, Offset] = selectADDR(N->getOperand(1), CurDAG);
- const auto [EvictionAndPrefetchHint, PolicyReg] =
- getMemCacheHintOperands(LD,
- {CodeAddrSpace, /*IsLoad=*/true,
- /*NumElts=*/1, /*EltWidth=*/FromTypeWidth, LD->isVolatile()},
- DL);
+ const auto [EvictionAndPrefetchHint, PolicyReg] = getMemCacheHintOperands(
+ LD,
+ {CodeAddrSpace, /*IsLoad=*/true,
+ /*NumElts=*/1, /*EltWidth=*/FromTypeWidth, LD->isVolatile()},
+ DL);
// Create the machine instruction DAG
SDValue Ops[] = {getI32Imm(Ordering, DL),
@@ -1491,11 +1492,12 @@ bool NVPTXDAGToDAGISel::tryLDG(MemSDNode *LD) {
ExtensionType != ISD::NON_EXTLOAD));
const auto [Base, Offset] = selectADDR(LD->getOperand(1), CurDAG);
- const auto [EvictionAndPrefetchHint, PolicyReg] = getMemCacheHintOperands(
- LD,
- {NVPTX::AddressSpace::Global,
- /*IsLoad=*/true, LD->getNumValues() - 1, FromTypeWidth, LD->isVolatile()},
- DL);
+ const auto [EvictionAndPrefetchHint, PolicyReg] =
+ getMemCacheHintOperands(LD,
+ {NVPTX::AddressSpace::Global,
+ /*IsLoad=*/true, LD->getNumValues() - 1,
+ FromTypeWidth, LD->isVolatile()},
+ DL);
SDValue Ops[] = {getI32Imm(FromType, DL),
getI32Imm(FromTypeWidth, DL),
getI32Imm(UsedBytesMask, DL),
@@ -1613,11 +1615,11 @@ bool NVPTXDAGToDAGISel::tryStore(SDNode *N) {
const auto [Base, Offset] = selectADDR(ST->getBasePtr(), CurDAG);
// Extract eviction/prefetch hint and cache policy register.
- const auto [EvictionAndPrefetchHint, PolicyReg] =
- getMemCacheHintOperands(ST,
- {CodeAddrSpace, /*IsLoad=*/false,
- /*NumElts=*/1, /*EltWidth=*/ToTypeWidth, ST->isVolatile()},
- DL);
+ const auto [EvictionAndPrefetchHint, PolicyReg] = getMemCacheHintOperands(
+ ST,
+ {CodeAddrSpace, /*IsLoad=*/false,
+ /*NumElts=*/1, /*EltWidth=*/ToTypeWidth, ST->isVolatile()},
+ DL);
SDValue Ops[] = {selectPossiblyImm(Value),
getI32Imm(Ordering, DL),
More information about the llvm-commits
mailing list