[llvm] [SPIRV] Implement bare bones lowering for G_PREFETCH (PR #215505)
Mariya Podchishchaeva via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 12 06:00:01 PDT 2026
https://github.com/Fznamznon updated https://github.com/llvm/llvm-project/pull/215505
>From 0baf687a521d58806bc0fd2be4847b0e5d894bbb Mon Sep 17 00:00:00 2001
From: Mariya Podchishchaeva <Mariya.Podchishchaeva at amd.com>
Date: Mon, 10 Aug 2026 12:34:34 -0500
Subject: [PATCH 1/4] [SPIRV] Implement bare bones lowering for G_PREFETCH
Map G_PREFETCH to OpenCL prefetch if SPV_KHR_untyped_pointers
is not enabled, otherwise drop.
Fixes https://github.com/llvm/llvm-project/issues/214265
---
llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h | 2 +-
.../Target/SPIRV/SPIRVInstructionSelector.cpp | 35 +++++++++++++++++++
llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp | 1 +
llvm/test/CodeGen/SPIRV/prefetch.ll | 23 ++++++++++++
4 files changed, 60 insertions(+), 1 deletion(-)
create mode 100644 llvm/test/CodeGen/SPIRV/prefetch.ll
diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
index d948e365ffebe..20a4ec1e54ce1 100644
--- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
+++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
@@ -472,7 +472,6 @@ class SPIRVGlobalRegistry : public SPIRVIRMapping {
SPIRVTypeInst getOpTypeFloat(uint32_t Width, MachineIRBuilder &MIRBuilder,
SPIRV::FPEncoding::FPEncoding FPEncode);
- SPIRVTypeInst getOpTypeVoid(MachineIRBuilder &MIRBuilder);
SPIRVTypeInst getOpTypeVector(uint32_t NumElems, SPIRVTypeInst ElemType,
MachineIRBuilder &MIRBuilder);
@@ -626,6 +625,7 @@ class SPIRVGlobalRegistry : public SPIRVIRMapping {
unsigned NumElements,
MachineInstr &I,
const SPIRVInstrInfo &TII);
+ SPIRVTypeInst getOpTypeVoid(MachineIRBuilder &MIRBuilder);
// Returns a pointer to a SPIR-V pointer type with the given base type and
// storage class. The base type will be translated to a SPIR-V type, and the
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index a13775f9d02ad..e433b6664f8c8 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -253,6 +253,8 @@ class SPIRVInstructionSelector : public InstructionSelector {
MachineInstr &I, unsigned Opcode) const;
bool selectDebugTrap(Register ResVReg, SPIRVTypeInst ResType,
MachineInstr &I) const;
+ bool selectPrefetch(Register ResVReg, SPIRVTypeInst ResType,
+ MachineInstr &I) const;
bool selectIntegerDot(Register ResVReg, SPIRVTypeInst ResType,
MachineInstr &I, bool Signed) const;
@@ -1451,6 +1453,8 @@ bool SPIRVInstructionSelector::spvSelect(Register ResVReg,
return true;
case TargetOpcode::G_DEBUGTRAP:
return selectDebugTrap(ResVReg, ResType, I);
+ case TargetOpcode::G_PREFETCH:
+ return selectPrefetch(ResVReg, ResType, I);
default:
return false;
@@ -1467,6 +1471,37 @@ bool SPIRVInstructionSelector::selectDebugTrap(Register ResVReg,
return true;
}
+bool SPIRVInstructionSelector::selectPrefetch(Register ResVReg,
+ SPIRVTypeInst ResType,
+ MachineInstr &I) const {
+ // llvm.prefetch is missing info about how many bytes to prefetch that
+ // OpUntypedPrefetchKHR instruction requires, so just drop the instruction
+ // in case untyped pointers are enabled since OCL prefetch cannot take
+ // untyped pointers.
+ if (STI.canUseExtension(SPIRV::Extension::SPV_KHR_untyped_pointers))
+ return true;
+
+ if (STI.canUseExtInstSet(SPIRV::InstructionSet::OpenCL_std)) {
+ MachineIRBuilder MIRBuilder(I);
+ const unsigned PointerSize = GR.getPointerSize();
+ const SPIRVTypeInst PointerSizeType =
+ GR.getOrCreateSPIRVIntegerType(PointerSize, MIRBuilder);
+ bool ZeroAsNull = !STI.isShader();
+
+ // Assume that a single element needs prefetch.
+ Register ConstIntOne =
+ GR.getOrCreateConstInt(1, I, PointerSizeType, TII, ZeroAsNull);
+
+ Register AddrVal = I.getOperand(0).getReg();
+ Register ExtReg = MRI->createVirtualRegister(
+ GR.getRegClass(GR.getOpTypeVoid(MIRBuilder)));
+ return selectExtInst(ExtReg, GR.getOpTypeVoid(MIRBuilder), I, CL::prefetch,
+ /*setMIFlags=*/false, /*useMSSrc=*/false,
+ {AddrVal, ConstIntOne});
+ }
+ return true;
+}
+
bool SPIRVInstructionSelector::selectExtInst(Register ResVReg,
SPIRVTypeInst ResType,
MachineInstr &I,
diff --git a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
index 516ba98d5bf7d..e45321640458b 100644
--- a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
@@ -473,6 +473,7 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) {
getActionDefinitionsBuilder(G_ATOMIC_CMPXCHG_WITH_SUCCESS).lower();
// TODO: add proper legalization rules.
getActionDefinitionsBuilder(G_ATOMIC_CMPXCHG).alwaysLegal();
+ getActionDefinitionsBuilder(G_PREFETCH).alwaysLegal();
getActionDefinitionsBuilder({G_UADDO, G_USUBO, G_UMULO, G_SMULO})
.alwaysLegal();
diff --git a/llvm/test/CodeGen/SPIRV/prefetch.ll b/llvm/test/CodeGen/SPIRV/prefetch.ll
new file mode 100644
index 0000000000000..26d1ce3b894a2
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/prefetch.ll
@@ -0,0 +1,23 @@
+; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv64-unknown-unknown %s -o - | FileCheck --check-prefixes=NO-EXT %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_KHR_untyped_pointers %s -o - | FileCheck --check-prefixes=EXT %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown --spirv-ext=+SPV_KHR_untyped_pointers %s -o - -filetype=obj | spirv-val %}
+
+; NO-EXT: %[[#EXTSET:]] = OpExtInstImport "OpenCL.std"
+
+define spir_kernel void @foo(ptr addrspace(1) %p) {
+ call void @llvm.prefetch.p1(ptr addrspace(1) %p, i32 0, i32 3, i32 1)
+ ret void
+}
+
+; NO-EXT: %[[#PTR:]] = OpTypePointer CrossWorkgroup
+; NO-EXT: %[[#VOID:]] = OpTypeVoid
+; NO-EXT: %5 = OpTypeFunction %4 %3
+; NO-EXT: %[[#I64:]] = OpTypeInt 64 0
+; NO-EXT: %[[#ONE:]] = OpConstant %[[#I64]] 1
+; NO-EXT: %9 = OpFunction %4 None %5
+; NO-EXT: %[[#P:]] = OpFunctionParameter %[[#PTR]]
+; NO-EXT: OpExtInst %[[#VOID]] %[[#EXTSET]] prefetch %[[#P]] %[[#ONE]]
+
+; EXT-NOT: OpExtInst{{.*}}prefetch
>From 5b2fcf8a104a6e8ba9ea1d0d8d1a65496ad989dd Mon Sep 17 00:00:00 2001
From: Mariya Podchishchaeva <Mariya.Podchishchaeva at amd.com>
Date: Tue, 11 Aug 2026 07:41:53 -0500
Subject: [PATCH 2/4] format
---
llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h | 1 -
llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp | 2 +-
2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
index 20a4ec1e54ce1..079d2af602274 100644
--- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
+++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
@@ -472,7 +472,6 @@ class SPIRVGlobalRegistry : public SPIRVIRMapping {
SPIRVTypeInst getOpTypeFloat(uint32_t Width, MachineIRBuilder &MIRBuilder,
SPIRV::FPEncoding::FPEncoding FPEncode);
-
SPIRVTypeInst getOpTypeVector(uint32_t NumElems, SPIRVTypeInst ElemType,
MachineIRBuilder &MIRBuilder);
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index e433b6664f8c8..0a125b4ec9187 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -254,7 +254,7 @@ class SPIRVInstructionSelector : public InstructionSelector {
bool selectDebugTrap(Register ResVReg, SPIRVTypeInst ResType,
MachineInstr &I) const;
bool selectPrefetch(Register ResVReg, SPIRVTypeInst ResType,
- MachineInstr &I) const;
+ MachineInstr &I) const;
bool selectIntegerDot(Register ResVReg, SPIRVTypeInst ResType,
MachineInstr &I, bool Signed) const;
>From 5ec37776e3930101bd06199e8d1e9105d209781b Mon Sep 17 00:00:00 2001
From: Mariya Podchishchaeva <Mariya.Podchishchaeva at amd.com>
Date: Tue, 11 Aug 2026 07:46:47 -0500
Subject: [PATCH 3/4] Fix checks
---
llvm/test/CodeGen/SPIRV/prefetch.ll | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/llvm/test/CodeGen/SPIRV/prefetch.ll b/llvm/test/CodeGen/SPIRV/prefetch.ll
index 26d1ce3b894a2..9edac269f3782 100644
--- a/llvm/test/CodeGen/SPIRV/prefetch.ll
+++ b/llvm/test/CodeGen/SPIRV/prefetch.ll
@@ -13,10 +13,10 @@ define spir_kernel void @foo(ptr addrspace(1) %p) {
; NO-EXT: %[[#PTR:]] = OpTypePointer CrossWorkgroup
; NO-EXT: %[[#VOID:]] = OpTypeVoid
-; NO-EXT: %5 = OpTypeFunction %4 %3
+; NO-EXT: %[[#FTY:]] = OpTypeFunction %[[#VOID]] %[[#PTR]]
; NO-EXT: %[[#I64:]] = OpTypeInt 64 0
; NO-EXT: %[[#ONE:]] = OpConstant %[[#I64]] 1
-; NO-EXT: %9 = OpFunction %4 None %5
+; NO-EXT: %[[#]] = OpFunction %[[#VOID]] None %[[#FTY]]
; NO-EXT: %[[#P:]] = OpFunctionParameter %[[#PTR]]
; NO-EXT: OpExtInst %[[#VOID]] %[[#EXTSET]] prefetch %[[#P]] %[[#ONE]]
>From 79a88d4d224c6a3e82d15235e44259f2321e0cfe Mon Sep 17 00:00:00 2001
From: Mariya Podchishchaeva <Mariya.Podchishchaeva at amd.com>
Date: Wed, 12 Aug 2026 06:01:33 -0500
Subject: [PATCH 4/4] Remove unused parameters
---
llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index 0a125b4ec9187..112584656c20e 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -253,8 +253,7 @@ class SPIRVInstructionSelector : public InstructionSelector {
MachineInstr &I, unsigned Opcode) const;
bool selectDebugTrap(Register ResVReg, SPIRVTypeInst ResType,
MachineInstr &I) const;
- bool selectPrefetch(Register ResVReg, SPIRVTypeInst ResType,
- MachineInstr &I) const;
+ bool selectPrefetch(MachineInstr &I) const;
bool selectIntegerDot(Register ResVReg, SPIRVTypeInst ResType,
MachineInstr &I, bool Signed) const;
@@ -1454,7 +1453,7 @@ bool SPIRVInstructionSelector::spvSelect(Register ResVReg,
case TargetOpcode::G_DEBUGTRAP:
return selectDebugTrap(ResVReg, ResType, I);
case TargetOpcode::G_PREFETCH:
- return selectPrefetch(ResVReg, ResType, I);
+ return selectPrefetch(I);
default:
return false;
@@ -1471,9 +1470,7 @@ bool SPIRVInstructionSelector::selectDebugTrap(Register ResVReg,
return true;
}
-bool SPIRVInstructionSelector::selectPrefetch(Register ResVReg,
- SPIRVTypeInst ResType,
- MachineInstr &I) const {
+bool SPIRVInstructionSelector::selectPrefetch(MachineInstr &I) const {
// llvm.prefetch is missing info about how many bytes to prefetch that
// OpUntypedPrefetchKHR instruction requires, so just drop the instruction
// in case untyped pointers are enabled since OCL prefetch cannot take
More information about the llvm-commits
mailing list