[llvm] [SPIR-V] Add lowering of ptrtoaddr (PR #184577)

Dmitry Sidorov via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 4 02:41:02 PST 2026


https://github.com/MrSidims updated https://github.com/llvm/llvm-project/pull/184577

>From c1684207775de5700593f26b447317facffcdec4 Mon Sep 17 00:00:00 2001
From: Dmitry Sidorov <Dmitry.Sidorov at amd.com>
Date: Tue, 3 Mar 2026 22:11:47 +0100
Subject: [PATCH 1/4] [SPIR-V] Add lowering of ptrtoaddr

The patch handles 2 scenarios:
1. In case if the following pattern present in LLVM IR
%a = ptrtoaddr
%b = ptrtoaddr
%diff = sub %a, %b

it's being replaced with a newly added spv_ptrdiff intrinsic to be
lowered as OpPtrDiff if allowed SPIR-V version > 1.4.

2. If the pattern is not recognized (for example there is a standalone
ptrtoaddr instruction in the module) of it allowed SPIR-V version is < 1.4,
then ptrtoaddr is being lowered to OpConvertPtrToU. It's not an ideal
solution.
---
 llvm/include/llvm/IR/IntrinsicsSPIRV.td       |  1 +
 llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp | 54 +++++++++++++++++++
 .../Target/SPIRV/SPIRVInstructionSelector.cpp |  6 +++
 llvm/test/CodeGen/SPIRV/ptrtoaddr-diff.ll     | 28 ++++++++++
 llvm/test/CodeGen/SPIRV/ptrtoaddr.ll          | 11 ++++
 5 files changed, 100 insertions(+)
 create mode 100644 llvm/test/CodeGen/SPIRV/ptrtoaddr-diff.ll
 create mode 100644 llvm/test/CodeGen/SPIRV/ptrtoaddr.ll

diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
index 9819f881b5c30..6d50fa853dafc 100644
--- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td
+++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
@@ -32,6 +32,7 @@ let TargetPrefix = "spv" in {
   def int_spv_insertelt : Intrinsic<[llvm_any_ty], [llvm_any_ty, llvm_any_ty, llvm_anyint_ty]>;
   def int_spv_const_composite : Intrinsic<[llvm_any_ty], [llvm_vararg_ty]>;
   def int_spv_bitcast : Intrinsic<[llvm_any_ty], [llvm_any_ty]>;
+  def int_spv_ptrdiff : DefaultAttrsIntrinsic<[llvm_anyint_ty], [llvm_anyptr_ty, LLVMMatchType<1>], [IntrNoMem]>;
   def int_spv_ptrcast : Intrinsic<[llvm_any_ty], [llvm_any_ty, llvm_metadata_ty, llvm_i32_ty], [ImmArg<ArgIndex<2>>]>;
   def int_spv_switch : Intrinsic<[], [llvm_any_ty, llvm_vararg_ty]>;
   def int_spv_loop_merge : Intrinsic<[], [llvm_vararg_ty]>;
diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
index 1c8774c59f065..2eb070c5c6100 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
@@ -146,6 +146,7 @@ class SPIRVEmitIntrinsics
 
   void preprocessCompositeConstants(IRBuilder<> &B);
   void preprocessUndefs(IRBuilder<> &B);
+  void preprocessPtrToAddrDiff(Function &F, IRBuilder<> &B);
 
   Type *reconstructType(Value *Op, bool UnknownElemTypeI8,
                         bool IsPostprocessing);
@@ -268,6 +269,7 @@ class SPIRVEmitIntrinsics
   Instruction *visitAtomicCmpXchgInst(AtomicCmpXchgInst &I);
   Instruction *visitUnreachableInst(UnreachableInst &I);
   Instruction *visitCallInst(CallInst &I);
+  Instruction *visitPtrToAddrInst(PtrToAddrInst &I);
 
   StringRef getPassName() const override { return "SPIRV emit intrinsics"; }
 
@@ -1725,6 +1727,57 @@ Instruction *SPIRVEmitIntrinsics::visitBitCastInst(BitCastInst &I) {
   return NewI;
 }
 
+Instruction *SPIRVEmitIntrinsics::visitPtrToAddrInst(PtrToAddrInst &I) {
+  // If ptrtoaddr instruction wasn't handled previously during
+  // sub(ptrtoaddr, ptrtoaddr) -> OpPtrDiff pattern lowering, then
+  // replace it with PtrToInt.
+  auto *PtrToInt =
+      CastInst::Create(Instruction::PtrToInt, I.getOperand(0), I.getType());
+  PtrToInt->insertBefore(I.getIterator());
+  replaceAllUsesWith(&I, PtrToInt);
+  I.eraseFromParent();
+  return PtrToInt;
+}
+
+// Recognize sub(ptrtoaddr(A), ptrtoaddr(B)) patterns and replace with
+// spv_ptrdiff intrinsic.
+void SPIRVEmitIntrinsics::preprocessPtrToAddrDiff(Function &F,
+                                                  IRBuilder<> &B) {
+  // OpPtrDiff was added in SPIR-V 1.4, check for it.
+  const SPIRVSubtarget *ST = TM->getSubtargetImpl(F);
+  if (!ST->isAtLeastSPIRVVer(VersionTuple(1, 4)))
+    return;
+
+  SmallVector<BinaryOperator *> SubsToReplace;
+  for (auto &I : instructions(F)) {
+    auto *Sub = dyn_cast<BinaryOperator>(&I);
+    if (!Sub || Sub->getOpcode() != Instruction::Sub)
+      continue;
+    if (isa<PtrToAddrInst>(Sub->getOperand(0)) &&
+        isa<PtrToAddrInst>(Sub->getOperand(1)))
+      SubsToReplace.push_back(Sub);
+  }
+
+  for (auto *Sub : SubsToReplace) {
+    auto *PtrToAddrA = cast<PtrToAddrInst>(Sub->getOperand(0));
+    auto *PtrToAddrB = cast<PtrToAddrInst>(Sub->getOperand(1));
+    Value *Ptr1 = PtrToAddrA->getOperand(0);
+    Value *Ptr2 = PtrToAddrB->getOperand(0);
+
+    B.SetInsertPoint(Sub);
+    auto *PtrDiff = B.CreateIntrinsic(
+        Intrinsic::spv_ptrdiff, {Sub->getType(), Ptr1->getType()},
+        {Ptr1, Ptr2});
+    Sub->replaceAllUsesWith(PtrDiff);
+    Sub->eraseFromParent();
+
+    if (PtrToAddrA->use_empty())
+      PtrToAddrA->eraseFromParent();
+    if (PtrToAddrB->use_empty())
+      PtrToAddrB->eraseFromParent();
+  }
+}
+
 void SPIRVEmitIntrinsics::insertAssignPtrTypeTargetExt(
     TargetExtType *AssignedType, Value *V, IRBuilder<> &B) {
   Type *VTy = V->getType();
@@ -3011,6 +3064,7 @@ bool SPIRVEmitIntrinsics::runOnFunction(Function &Func) {
 
   preprocessUndefs(B);
   preprocessCompositeConstants(B);
+  preprocessPtrToAddrDiff(Func, B);
   SmallVector<Instruction *> Worklist(
       llvm::make_pointer_range(instructions(Func)));
 
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index 344628f258229..e5cd4e044ebcd 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -609,6 +609,7 @@ static bool intrinsicHasSideEffects(Intrinsic::ID ID) {
   case Intrinsic::spv_num_subgroups:
   case Intrinsic::spv_num_workgroups:
   case Intrinsic::spv_ptrcast:
+  case Intrinsic::spv_ptrdiff:
   case Intrinsic::spv_radians:
   case Intrinsic::spv_reflect:
   case Intrinsic::spv_refract:
@@ -3798,6 +3799,11 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg,
       report_fatal_error("incompatible result and operand types in a bitcast");
     return selectOpWithSrcs(ResVReg, ResType, I, {OpReg}, SPIRV::OpBitcast);
   }
+  case Intrinsic::spv_ptrdiff:
+    return selectOpWithSrcs(ResVReg, ResType, I,
+                            {I.getOperand(2).getReg(),
+                             I.getOperand(3).getReg()},
+                            SPIRV::OpPtrDiff);
   case Intrinsic::spv_unref_global:
   case Intrinsic::spv_init_global: {
     MachineInstr *MI = MRI->getVRegDef(I.getOperand(1).getReg());
diff --git a/llvm/test/CodeGen/SPIRV/ptrtoaddr-diff.ll b/llvm/test/CodeGen/SPIRV/ptrtoaddr-diff.ll
new file mode 100644
index 0000000000000..68410245a98fd
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/ptrtoaddr-diff.ll
@@ -0,0 +1,28 @@
+; Test sub(ptrtoaddr, ptrtoaddr) -> OpPtrDiff for SPIR-V 1.4+
+; RUN: llc -O0 -mtriple=spirv64v1.4-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV-14
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64v1.4-unknown-unknown %s -o - -filetype=obj | spirv-val --target-env spv1.4 %}
+
+; Test fallback to OpConvertPtrToU + ISub for SPIR-V < 1.4
+; RUN: llc -O0 -mtriple=spirv64v1.3-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV-13
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64v1.3-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+; CHECK-SPIRV-14: %[[#Arg1:]] = OpFunctionParameter %[[#]]
+; CHECK-SPIRV-14: %[[#Arg2:]] = OpFunctionParameter %[[#]]
+; CHECK-SPIRV-14: %[[#]] = OpPtrDiff %[[#]] %[[#Arg1]] %[[#Arg2]]
+; CHECK-SPIRV-14-NOT: OpConvertPtrToU
+
+; CHECK-SPIRV-13: %[[#Arg1:]] = OpFunctionParameter %[[#]]
+; CHECK-SPIRV-13: %[[#Arg2:]] = OpFunctionParameter %[[#]]
+; CHECK-SPIRV-13: %[[#Conv1:]] = OpConvertPtrToU %[[#]] %[[#Arg1]]
+; CHECK-SPIRV-13: %[[#Conv2:]] = OpConvertPtrToU %[[#]] %[[#Arg2]]
+; CHECK-SPIRV-13: %[[#]] = OpISub %[[#]] %[[#Conv1]] %[[#Conv2]]
+; CHECK-SPIRV-13-NOT: OpPtrDiff
+
+define spir_kernel void @test_ptrdiff(ptr addrspace(1) %p1, ptr addrspace(1) %p2, ptr addrspace(1) %res) {
+entry:
+  %a = ptrtoaddr ptr addrspace(1) %p1 to i64
+  %b = ptrtoaddr ptr addrspace(1) %p2 to i64
+  %diff = sub i64 %a, %b
+  store i64 %diff, ptr addrspace(1) %res
+  ret void
+}
diff --git a/llvm/test/CodeGen/SPIRV/ptrtoaddr.ll b/llvm/test/CodeGen/SPIRV/ptrtoaddr.ll
new file mode 100644
index 0000000000000..11626649f5bb8
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/ptrtoaddr.ll
@@ -0,0 +1,11 @@
+; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+; CHECK: OpConvertPtrToU
+
+define spir_kernel void @test_ptrtoaddr(ptr addrspace(1) %p, ptr addrspace(1) %res) {
+entry:
+  %addr = ptrtoaddr ptr addrspace(1) %p to i64
+  store i64 %addr, ptr addrspace(1) %res
+  ret void
+}

>From fd01101214b793e1215bb62c9b6f3850f35112b9 Mon Sep 17 00:00:00 2001
From: Dmitry Sidorov <Dmitry.Sidorov at amd.com>
Date: Wed, 4 Mar 2026 10:54:45 +0100
Subject: [PATCH 2/4] format

---
 llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp      | 9 ++++-----
 llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp | 7 +++----
 2 files changed, 7 insertions(+), 9 deletions(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
index 2eb070c5c6100..bee7814f95ca8 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
@@ -1741,8 +1741,7 @@ Instruction *SPIRVEmitIntrinsics::visitPtrToAddrInst(PtrToAddrInst &I) {
 
 // Recognize sub(ptrtoaddr(A), ptrtoaddr(B)) patterns and replace with
 // spv_ptrdiff intrinsic.
-void SPIRVEmitIntrinsics::preprocessPtrToAddrDiff(Function &F,
-                                                  IRBuilder<> &B) {
+void SPIRVEmitIntrinsics::preprocessPtrToAddrDiff(Function &F, IRBuilder<> &B) {
   // OpPtrDiff was added in SPIR-V 1.4, check for it.
   const SPIRVSubtarget *ST = TM->getSubtargetImpl(F);
   if (!ST->isAtLeastSPIRVVer(VersionTuple(1, 4)))
@@ -1765,9 +1764,9 @@ void SPIRVEmitIntrinsics::preprocessPtrToAddrDiff(Function &F,
     Value *Ptr2 = PtrToAddrB->getOperand(0);
 
     B.SetInsertPoint(Sub);
-    auto *PtrDiff = B.CreateIntrinsic(
-        Intrinsic::spv_ptrdiff, {Sub->getType(), Ptr1->getType()},
-        {Ptr1, Ptr2});
+    auto *PtrDiff =
+        B.CreateIntrinsic(Intrinsic::spv_ptrdiff,
+                          {Sub->getType(), Ptr1->getType()}, {Ptr1, Ptr2});
     Sub->replaceAllUsesWith(PtrDiff);
     Sub->eraseFromParent();
 
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index e5cd4e044ebcd..32d2c7e9d1594 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -3800,10 +3800,9 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg,
     return selectOpWithSrcs(ResVReg, ResType, I, {OpReg}, SPIRV::OpBitcast);
   }
   case Intrinsic::spv_ptrdiff:
-    return selectOpWithSrcs(ResVReg, ResType, I,
-                            {I.getOperand(2).getReg(),
-                             I.getOperand(3).getReg()},
-                            SPIRV::OpPtrDiff);
+    return selectOpWithSrcs(
+        ResVReg, ResType, I,
+        {I.getOperand(2).getReg(), I.getOperand(3).getReg()}, SPIRV::OpPtrDiff);
   case Intrinsic::spv_unref_global:
   case Intrinsic::spv_init_global: {
     MachineInstr *MI = MRI->getVRegDef(I.getOperand(1).getReg());

>From da65ab9211e5f6ee361f592efb62963605cd3ea0 Mon Sep 17 00:00:00 2001
From: Dmitry Sidorov <Dmitry.Sidorov at amd.com>
Date: Wed, 4 Mar 2026 11:39:08 +0100
Subject: [PATCH 3/4] remove ptrdiff transform

---
 llvm/include/llvm/IR/IntrinsicsSPIRV.td       |  1 -
 llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp | 40 -------------------
 .../Target/SPIRV/SPIRVInstructionSelector.cpp |  5 ---
 llvm/test/CodeGen/SPIRV/ptrtoaddr-diff.ll     | 28 -------------
 4 files changed, 74 deletions(-)
 delete mode 100644 llvm/test/CodeGen/SPIRV/ptrtoaddr-diff.ll

diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
index 6d50fa853dafc..9819f881b5c30 100644
--- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td
+++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
@@ -32,7 +32,6 @@ let TargetPrefix = "spv" in {
   def int_spv_insertelt : Intrinsic<[llvm_any_ty], [llvm_any_ty, llvm_any_ty, llvm_anyint_ty]>;
   def int_spv_const_composite : Intrinsic<[llvm_any_ty], [llvm_vararg_ty]>;
   def int_spv_bitcast : Intrinsic<[llvm_any_ty], [llvm_any_ty]>;
-  def int_spv_ptrdiff : DefaultAttrsIntrinsic<[llvm_anyint_ty], [llvm_anyptr_ty, LLVMMatchType<1>], [IntrNoMem]>;
   def int_spv_ptrcast : Intrinsic<[llvm_any_ty], [llvm_any_ty, llvm_metadata_ty, llvm_i32_ty], [ImmArg<ArgIndex<2>>]>;
   def int_spv_switch : Intrinsic<[], [llvm_any_ty, llvm_vararg_ty]>;
   def int_spv_loop_merge : Intrinsic<[], [llvm_vararg_ty]>;
diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
index bee7814f95ca8..cb1b3c82c8022 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
@@ -146,7 +146,6 @@ class SPIRVEmitIntrinsics
 
   void preprocessCompositeConstants(IRBuilder<> &B);
   void preprocessUndefs(IRBuilder<> &B);
-  void preprocessPtrToAddrDiff(Function &F, IRBuilder<> &B);
 
   Type *reconstructType(Value *Op, bool UnknownElemTypeI8,
                         bool IsPostprocessing);
@@ -1739,44 +1738,6 @@ Instruction *SPIRVEmitIntrinsics::visitPtrToAddrInst(PtrToAddrInst &I) {
   return PtrToInt;
 }
 
-// Recognize sub(ptrtoaddr(A), ptrtoaddr(B)) patterns and replace with
-// spv_ptrdiff intrinsic.
-void SPIRVEmitIntrinsics::preprocessPtrToAddrDiff(Function &F, IRBuilder<> &B) {
-  // OpPtrDiff was added in SPIR-V 1.4, check for it.
-  const SPIRVSubtarget *ST = TM->getSubtargetImpl(F);
-  if (!ST->isAtLeastSPIRVVer(VersionTuple(1, 4)))
-    return;
-
-  SmallVector<BinaryOperator *> SubsToReplace;
-  for (auto &I : instructions(F)) {
-    auto *Sub = dyn_cast<BinaryOperator>(&I);
-    if (!Sub || Sub->getOpcode() != Instruction::Sub)
-      continue;
-    if (isa<PtrToAddrInst>(Sub->getOperand(0)) &&
-        isa<PtrToAddrInst>(Sub->getOperand(1)))
-      SubsToReplace.push_back(Sub);
-  }
-
-  for (auto *Sub : SubsToReplace) {
-    auto *PtrToAddrA = cast<PtrToAddrInst>(Sub->getOperand(0));
-    auto *PtrToAddrB = cast<PtrToAddrInst>(Sub->getOperand(1));
-    Value *Ptr1 = PtrToAddrA->getOperand(0);
-    Value *Ptr2 = PtrToAddrB->getOperand(0);
-
-    B.SetInsertPoint(Sub);
-    auto *PtrDiff =
-        B.CreateIntrinsic(Intrinsic::spv_ptrdiff,
-                          {Sub->getType(), Ptr1->getType()}, {Ptr1, Ptr2});
-    Sub->replaceAllUsesWith(PtrDiff);
-    Sub->eraseFromParent();
-
-    if (PtrToAddrA->use_empty())
-      PtrToAddrA->eraseFromParent();
-    if (PtrToAddrB->use_empty())
-      PtrToAddrB->eraseFromParent();
-  }
-}
-
 void SPIRVEmitIntrinsics::insertAssignPtrTypeTargetExt(
     TargetExtType *AssignedType, Value *V, IRBuilder<> &B) {
   Type *VTy = V->getType();
@@ -3063,7 +3024,6 @@ bool SPIRVEmitIntrinsics::runOnFunction(Function &Func) {
 
   preprocessUndefs(B);
   preprocessCompositeConstants(B);
-  preprocessPtrToAddrDiff(Func, B);
   SmallVector<Instruction *> Worklist(
       llvm::make_pointer_range(instructions(Func)));
 
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index 32d2c7e9d1594..344628f258229 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -609,7 +609,6 @@ static bool intrinsicHasSideEffects(Intrinsic::ID ID) {
   case Intrinsic::spv_num_subgroups:
   case Intrinsic::spv_num_workgroups:
   case Intrinsic::spv_ptrcast:
-  case Intrinsic::spv_ptrdiff:
   case Intrinsic::spv_radians:
   case Intrinsic::spv_reflect:
   case Intrinsic::spv_refract:
@@ -3799,10 +3798,6 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg,
       report_fatal_error("incompatible result and operand types in a bitcast");
     return selectOpWithSrcs(ResVReg, ResType, I, {OpReg}, SPIRV::OpBitcast);
   }
-  case Intrinsic::spv_ptrdiff:
-    return selectOpWithSrcs(
-        ResVReg, ResType, I,
-        {I.getOperand(2).getReg(), I.getOperand(3).getReg()}, SPIRV::OpPtrDiff);
   case Intrinsic::spv_unref_global:
   case Intrinsic::spv_init_global: {
     MachineInstr *MI = MRI->getVRegDef(I.getOperand(1).getReg());
diff --git a/llvm/test/CodeGen/SPIRV/ptrtoaddr-diff.ll b/llvm/test/CodeGen/SPIRV/ptrtoaddr-diff.ll
deleted file mode 100644
index 68410245a98fd..0000000000000
--- a/llvm/test/CodeGen/SPIRV/ptrtoaddr-diff.ll
+++ /dev/null
@@ -1,28 +0,0 @@
-; Test sub(ptrtoaddr, ptrtoaddr) -> OpPtrDiff for SPIR-V 1.4+
-; RUN: llc -O0 -mtriple=spirv64v1.4-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV-14
-; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64v1.4-unknown-unknown %s -o - -filetype=obj | spirv-val --target-env spv1.4 %}
-
-; Test fallback to OpConvertPtrToU + ISub for SPIR-V < 1.4
-; RUN: llc -O0 -mtriple=spirv64v1.3-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV-13
-; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64v1.3-unknown-unknown %s -o - -filetype=obj | spirv-val %}
-
-; CHECK-SPIRV-14: %[[#Arg1:]] = OpFunctionParameter %[[#]]
-; CHECK-SPIRV-14: %[[#Arg2:]] = OpFunctionParameter %[[#]]
-; CHECK-SPIRV-14: %[[#]] = OpPtrDiff %[[#]] %[[#Arg1]] %[[#Arg2]]
-; CHECK-SPIRV-14-NOT: OpConvertPtrToU
-
-; CHECK-SPIRV-13: %[[#Arg1:]] = OpFunctionParameter %[[#]]
-; CHECK-SPIRV-13: %[[#Arg2:]] = OpFunctionParameter %[[#]]
-; CHECK-SPIRV-13: %[[#Conv1:]] = OpConvertPtrToU %[[#]] %[[#Arg1]]
-; CHECK-SPIRV-13: %[[#Conv2:]] = OpConvertPtrToU %[[#]] %[[#Arg2]]
-; CHECK-SPIRV-13: %[[#]] = OpISub %[[#]] %[[#Conv1]] %[[#Conv2]]
-; CHECK-SPIRV-13-NOT: OpPtrDiff
-
-define spir_kernel void @test_ptrdiff(ptr addrspace(1) %p1, ptr addrspace(1) %p2, ptr addrspace(1) %res) {
-entry:
-  %a = ptrtoaddr ptr addrspace(1) %p1 to i64
-  %b = ptrtoaddr ptr addrspace(1) %p2 to i64
-  %diff = sub i64 %a, %b
-  store i64 %diff, ptr addrspace(1) %res
-  ret void
-}

>From 2aa79e592e16656b6ecdb6c1317b20fe24e4307e Mon Sep 17 00:00:00 2001
From: Dmitry Sidorov <Dmitry.Sidorov at amd.com>
Date: Wed, 4 Mar 2026 11:40:42 +0100
Subject: [PATCH 4/4] correct comment

---
 llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
index cb1b3c82c8022..7ce4c0f54eff3 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
@@ -1727,9 +1727,7 @@ Instruction *SPIRVEmitIntrinsics::visitBitCastInst(BitCastInst &I) {
 }
 
 Instruction *SPIRVEmitIntrinsics::visitPtrToAddrInst(PtrToAddrInst &I) {
-  // If ptrtoaddr instruction wasn't handled previously during
-  // sub(ptrtoaddr, ptrtoaddr) -> OpPtrDiff pattern lowering, then
-  // replace it with PtrToInt.
+  // Replace PtrToAddr with PtrToInt.
   auto *PtrToInt =
       CastInst::Create(Instruction::PtrToInt, I.getOperand(0), I.getType());
   PtrToInt->insertBefore(I.getIterator());



More information about the llvm-commits mailing list