[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