[llvm-branch-commits] [mlir] 3fec9c7 - [mlir][SPIR-V] Add SPIRVToLLVM direct conversions for cast, CL, GL and logical ops (#202506)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue Jun 9 03:04:37 PDT 2026


Author: Arseniy Obolenskiy
Date: 2026-06-09T11:07:36+02:00
New Revision: 3fec9c702b597e1a0204ff30137ae8d1557e395c

URL: https://github.com/llvm/llvm-project/commit/3fec9c702b597e1a0204ff30137ae8d1557e395c
DIFF: https://github.com/llvm/llvm-project/commit/3fec9c702b597e1a0204ff30137ae8d1557e395c.diff

LOG: [mlir][SPIR-V] Add SPIRVToLLVM direct conversions for cast, CL, GL and logical ops (#202506)

Lower the OpenCL extended instruction set math ops, GL math ops (Trunc,
Asin, Acos, Atan), logical Ordered/Unordered, and the pointer cast ops
to their LLVM dialect equivalents

Added: 
    mlir/test/Conversion/SPIRVToLLVM/cl-ops-to-llvm.mlir

Modified: 
    mlir/lib/Conversion/SPIRVToLLVM/SPIRVToLLVM.cpp
    mlir/test/Conversion/SPIRVToLLVM/cast-ops-to-llvm.mlir
    mlir/test/Conversion/SPIRVToLLVM/gl-ops-to-llvm.mlir
    mlir/test/Conversion/SPIRVToLLVM/logical-ops-to-llvm.mlir

Removed: 
    


################################################################################
diff  --git a/mlir/lib/Conversion/SPIRVToLLVM/SPIRVToLLVM.cpp b/mlir/lib/Conversion/SPIRVToLLVM/SPIRVToLLVM.cpp
index daa4d020ff063..c43415b27b1b3 100644
--- a/mlir/lib/Conversion/SPIRVToLLVM/SPIRVToLLVM.cpp
+++ b/mlir/lib/Conversion/SPIRVToLLVM/SPIRVToLLVM.cpp
@@ -1844,6 +1844,12 @@ void mlir::populateSPIRVToLLVMConversionPatterns(
       IndirectCastPattern<spirv::FConvertOp, LLVM::FPExtOp, LLVM::FPTruncOp>,
       IndirectCastPattern<spirv::SConvertOp, LLVM::SExtOp, LLVM::TruncOp>,
       IndirectCastPattern<spirv::UConvertOp, LLVM::ZExtOp, LLVM::TruncOp>,
+      DirectConversionPattern<spirv::ConvertPtrToUOp, LLVM::PtrToIntOp>,
+      DirectConversionPattern<spirv::ConvertUToPtrOp, LLVM::IntToPtrOp>,
+      DirectConversionPattern<spirv::PtrCastToGenericOp, LLVM::AddrSpaceCastOp>,
+      DirectConversionPattern<spirv::GenericCastToPtrOp, LLVM::AddrSpaceCastOp>,
+      DirectConversionPattern<spirv::GenericCastToPtrExplicitOp,
+                              LLVM::AddrSpaceCastOp>,
 
       // Comparison ops
       IComparePattern<spirv::IEqualOp, LLVM::ICmpPredicate::eq>,
@@ -1861,6 +1867,8 @@ void mlir::populateSPIRVToLLVMConversionPatterns(
       FComparePattern<spirv::FUnordLessThanEqualOp, LLVM::FCmpPredicate::ule>,
       FComparePattern<spirv::FUnordLessThanOp, LLVM::FCmpPredicate::ult>,
       FComparePattern<spirv::FUnordNotEqualOp, LLVM::FCmpPredicate::une>,
+      FComparePattern<spirv::OrderedOp, LLVM::FCmpPredicate::ord>,
+      FComparePattern<spirv::UnorderedOp, LLVM::FCmpPredicate::uno>,
       IComparePattern<spirv::SGreaterThanOp, LLVM::ICmpPredicate::sgt>,
       IComparePattern<spirv::SGreaterThanEqualOp, LLVM::ICmpPredicate::sge>,
       IComparePattern<spirv::SLessThanEqualOp, LLVM::ICmpPredicate::sle>,
@@ -1904,8 +1912,45 @@ void mlir::populateSPIRVToLLVMConversionPatterns(
       DirectConversionPattern<spirv::GLSqrtOp, LLVM::SqrtOp>,
       DirectConversionPattern<spirv::GLUMaxOp, LLVM::UMaxOp>,
       DirectConversionPattern<spirv::GLUMinOp, LLVM::UMinOp>,
+      DirectConversionPattern<spirv::GLTruncOp, LLVM::FTruncOp>,
+      DirectConversionPattern<spirv::GLAsinOp, LLVM::ASinOp>,
+      DirectConversionPattern<spirv::GLAcosOp, LLVM::ACosOp>,
+      DirectConversionPattern<spirv::GLAtanOp, LLVM::ATanOp>,
       InverseSqrtPattern, SAbsPattern, TanPattern, TanhPattern,
 
+      // OpenCL extended instruction set ops
+      DirectConversionPattern<spirv::CLCeilOp, LLVM::FCeilOp>,
+      DirectConversionPattern<spirv::CLCosOp, LLVM::CosOp>,
+      DirectConversionPattern<spirv::CLExpOp, LLVM::ExpOp>,
+      DirectConversionPattern<spirv::CLExp2Op, LLVM::Exp2Op>,
+      DirectConversionPattern<spirv::CLExp10Op, LLVM::Exp10Op>,
+      DirectConversionPattern<spirv::CLFAbsOp, LLVM::FAbsOp>,
+      DirectConversionPattern<spirv::CLFloorOp, LLVM::FFloorOp>,
+      DirectConversionPattern<spirv::CLFmaOp, LLVM::FMAOp>,
+      DirectConversionPattern<spirv::CLFMaxOp, LLVM::MaxNumOp>,
+      DirectConversionPattern<spirv::CLFMinOp, LLVM::MinNumOp>,
+      DirectConversionPattern<spirv::CLLogOp, LLVM::LogOp>,
+      DirectConversionPattern<spirv::CLLog2Op, LLVM::Log2Op>,
+      DirectConversionPattern<spirv::CLLog10Op, LLVM::Log10Op>,
+      DirectConversionPattern<spirv::CLPowOp, LLVM::PowOp>,
+      DirectConversionPattern<spirv::CLRintOp, LLVM::RintOp>,
+      DirectConversionPattern<spirv::CLRoundOp, LLVM::RoundOp>,
+      DirectConversionPattern<spirv::CLSinOp, LLVM::SinOp>,
+      DirectConversionPattern<spirv::CLSinhOp, LLVM::SinhOp>,
+      DirectConversionPattern<spirv::CLCoshOp, LLVM::CoshOp>,
+      DirectConversionPattern<spirv::CLTanOp, LLVM::TanOp>,
+      DirectConversionPattern<spirv::CLTanhOp, LLVM::TanhOp>,
+      DirectConversionPattern<spirv::CLAsinOp, LLVM::ASinOp>,
+      DirectConversionPattern<spirv::CLAcosOp, LLVM::ACosOp>,
+      DirectConversionPattern<spirv::CLAtanOp, LLVM::ATanOp>,
+      DirectConversionPattern<spirv::CLAtan2Op, LLVM::ATan2Op>,
+      DirectConversionPattern<spirv::CLSqrtOp, LLVM::SqrtOp>,
+      DirectConversionPattern<spirv::CLTruncOp, LLVM::FTruncOp>,
+      DirectConversionPattern<spirv::CLSMaxOp, LLVM::SMaxOp>,
+      DirectConversionPattern<spirv::CLSMinOp, LLVM::SMinOp>,
+      DirectConversionPattern<spirv::CLUMaxOp, LLVM::UMaxOp>,
+      DirectConversionPattern<spirv::CLUMinOp, LLVM::UMinOp>,
+
       // Logical ops
       DirectConversionPattern<spirv::LogicalAndOp, LLVM::AndOp>,
       DirectConversionPattern<spirv::LogicalOrOp, LLVM::OrOp>,

diff  --git a/mlir/test/Conversion/SPIRVToLLVM/cast-ops-to-llvm.mlir b/mlir/test/Conversion/SPIRVToLLVM/cast-ops-to-llvm.mlir
index 2026027a6dace..586dea350336a 100644
--- a/mlir/test/Conversion/SPIRVToLLVM/cast-ops-to-llvm.mlir
+++ b/mlir/test/Conversion/SPIRVToLLVM/cast-ops-to-llvm.mlir
@@ -189,3 +189,58 @@ spirv.func @uconvert_vector(%arg0: vector<3xi32>, %arg1: vector<3xi64>) "None" {
   %1 = spirv.UConvert %arg1: vector<3xi64> to vector<3xi32>
   spirv.Return
 }
+
+//===----------------------------------------------------------------------===//
+// spirv.ConvertPtrToU
+//===----------------------------------------------------------------------===//
+
+// CHECK-LABEL: @convert_ptr_to_u
+spirv.func @convert_ptr_to_u(%arg0 : !spirv.ptr<i32, Generic>) "None" {
+  // CHECK: llvm.ptrtoint %{{.*}} : !llvm.ptr to i32
+  %0 = spirv.ConvertPtrToU %arg0 : !spirv.ptr<i32, Generic> to i32
+  spirv.Return
+}
+
+//===----------------------------------------------------------------------===//
+// spirv.ConvertUToPtr
+//===----------------------------------------------------------------------===//
+
+// CHECK-LABEL: @convert_u_to_ptr
+spirv.func @convert_u_to_ptr(%arg0 : i32) "None" {
+  // CHECK: llvm.inttoptr %{{.*}} : i32 to !llvm.ptr
+  %0 = spirv.ConvertUToPtr %arg0 : i32 to !spirv.ptr<i32, Generic>
+  spirv.Return
+}
+
+//===----------------------------------------------------------------------===//
+// spirv.PtrCastToGeneric
+//===----------------------------------------------------------------------===//
+
+// CHECK-LABEL: @ptr_cast_to_generic
+spirv.func @ptr_cast_to_generic(%arg0 : !spirv.ptr<f32, CrossWorkgroup>) "None" {
+  // CHECK: llvm.addrspacecast %{{.*}} : !llvm.ptr to !llvm.ptr
+  %0 = spirv.PtrCastToGeneric %arg0 : !spirv.ptr<f32, CrossWorkgroup> to !spirv.ptr<f32, Generic>
+  spirv.Return
+}
+
+//===----------------------------------------------------------------------===//
+// spirv.GenericCastToPtr
+//===----------------------------------------------------------------------===//
+
+// CHECK-LABEL: @generic_cast_to_ptr
+spirv.func @generic_cast_to_ptr(%arg0 : !spirv.ptr<vector<2xi32>, Generic>) "None" {
+  // CHECK: llvm.addrspacecast %{{.*}} : !llvm.ptr to !llvm.ptr
+  %0 = spirv.GenericCastToPtr %arg0 : !spirv.ptr<vector<2xi32>, Generic> to !spirv.ptr<vector<2xi32>, CrossWorkgroup>
+  spirv.Return
+}
+
+//===----------------------------------------------------------------------===//
+// spirv.GenericCastToPtrExplicit
+//===----------------------------------------------------------------------===//
+
+// CHECK-LABEL: @generic_cast_to_ptr_explicit
+spirv.func @generic_cast_to_ptr_explicit(%arg0 : !spirv.ptr<vector<2xi32>, Generic>) "None" {
+  // CHECK: llvm.addrspacecast %{{.*}} : !llvm.ptr to !llvm.ptr
+  %0 = spirv.GenericCastToPtrExplicit %arg0 : !spirv.ptr<vector<2xi32>, Generic> to !spirv.ptr<vector<2xi32>, CrossWorkgroup>
+  spirv.Return
+}

diff  --git a/mlir/test/Conversion/SPIRVToLLVM/cl-ops-to-llvm.mlir b/mlir/test/Conversion/SPIRVToLLVM/cl-ops-to-llvm.mlir
new file mode 100644
index 0000000000000..f0568e1035cd9
--- /dev/null
+++ b/mlir/test/Conversion/SPIRVToLLVM/cl-ops-to-llvm.mlir
@@ -0,0 +1,101 @@
+// RUN: mlir-opt -convert-spirv-to-llvm %s | FileCheck %s
+
+//===----------------------------------------------------------------------===//
+// Unary floating-point OpenCL ops mapped to LLVM intrinsics
+//===----------------------------------------------------------------------===//
+
+// CHECK-LABEL: @cl_unary_float
+spirv.func @cl_unary_float(%arg0: f32, %arg1: vector<3xf32>) "None" {
+  // CHECK: llvm.intr.ceil(%{{.*}}) : (f32) -> f32
+  %0 = spirv.CL.ceil %arg0 : f32
+  // CHECK: llvm.intr.cos(%{{.*}}) : (f32) -> f32
+  %1 = spirv.CL.cos %arg0 : f32
+  // CHECK: llvm.intr.exp(%{{.*}}) : (f32) -> f32
+  %2 = spirv.CL.exp %arg0 : f32
+  // CHECK: llvm.intr.exp2(%{{.*}}) : (f32) -> f32
+  %3 = spirv.CL.exp2 %arg0 : f32
+  // CHECK: llvm.intr.exp10(%{{.*}}) : (f32) -> f32
+  %4 = spirv.CL.exp10 %arg0 : f32
+  // CHECK: llvm.intr.fabs(%{{.*}}) : (f32) -> f32
+  %5 = spirv.CL.fabs %arg0 : f32
+  // CHECK: llvm.intr.floor(%{{.*}}) : (f32) -> f32
+  %6 = spirv.CL.floor %arg0 : f32
+  // CHECK: llvm.intr.log(%{{.*}}) : (f32) -> f32
+  %7 = spirv.CL.log %arg0 : f32
+  // CHECK: llvm.intr.log2(%{{.*}}) : (f32) -> f32
+  %8 = spirv.CL.log2 %arg0 : f32
+  // CHECK: llvm.intr.log10(%{{.*}}) : (f32) -> f32
+  %9 = spirv.CL.log10 %arg0 : f32
+  // CHECK: llvm.intr.rint(%{{.*}}) : (f32) -> f32
+  %10 = spirv.CL.rint %arg0 : f32
+  // CHECK: llvm.intr.round(%{{.*}}) : (f32) -> f32
+  %11 = spirv.CL.round %arg0 : f32
+  // CHECK: llvm.intr.sin(%{{.*}}) : (f32) -> f32
+  %12 = spirv.CL.sin %arg0 : f32
+  // CHECK: llvm.intr.sinh(%{{.*}}) : (f32) -> f32
+  %13 = spirv.CL.sinh %arg0 : f32
+  // CHECK: llvm.intr.cosh(%{{.*}}) : (f32) -> f32
+  %14 = spirv.CL.cosh %arg0 : f32
+  // CHECK: llvm.intr.tan(%{{.*}}) : (f32) -> f32
+  %15 = spirv.CL.tan %arg0 : f32
+  // CHECK: llvm.intr.tanh(%{{.*}}) : (f32) -> f32
+  %16 = spirv.CL.tanh %arg0 : f32
+  // CHECK: llvm.intr.asin(%{{.*}}) : (f32) -> f32
+  %17 = spirv.CL.asin %arg0 : f32
+  // CHECK: llvm.intr.acos(%{{.*}}) : (f32) -> f32
+  %18 = spirv.CL.acos %arg0 : f32
+  // CHECK: llvm.intr.atan(%{{.*}}) : (f32) -> f32
+  %19 = spirv.CL.atan %arg0 : f32
+  // CHECK: llvm.intr.sqrt(%{{.*}}) : (f32) -> f32
+  %20 = spirv.CL.sqrt %arg0 : f32
+  // CHECK: llvm.intr.trunc(%{{.*}}) : (f32) -> f32
+  %21 = spirv.CL.trunc %arg0 : f32
+  // CHECK: llvm.intr.sin(%{{.*}}) : (vector<3xf32>) -> vector<3xf32>
+  %22 = spirv.CL.sin %arg1 : vector<3xf32>
+  spirv.Return
+}
+
+//===----------------------------------------------------------------------===//
+// Binary floating-point OpenCL ops
+//===----------------------------------------------------------------------===//
+
+// CHECK-LABEL: @cl_binary_float
+spirv.func @cl_binary_float(%arg0: f32, %arg1: f32) "None" {
+  // CHECK: llvm.intr.pow(%{{.*}}, %{{.*}}) : (f32, f32) -> f32
+  %0 = spirv.CL.pow %arg0, %arg1 : f32
+  // CHECK: llvm.intr.atan2(%{{.*}}, %{{.*}}) : (f32, f32) -> f32
+  %1 = spirv.CL.atan2 %arg0, %arg1 : f32
+  // CHECK: llvm.intr.maxnum(%{{.*}}, %{{.*}}) : (f32, f32) -> f32
+  %2 = spirv.CL.fmax %arg0, %arg1 : f32
+  // CHECK: llvm.intr.minnum(%{{.*}}, %{{.*}}) : (f32, f32) -> f32
+  %3 = spirv.CL.fmin %arg0, %arg1 : f32
+  spirv.Return
+}
+
+//===----------------------------------------------------------------------===//
+// Ternary FP OpenCL ops
+//===----------------------------------------------------------------------===//
+
+// CHECK-LABEL: @cl_fma
+spirv.func @cl_fma(%arg0: f32, %arg1: f32, %arg2: f32) "None" {
+  // CHECK: llvm.intr.fma(%{{.*}}, %{{.*}}, %{{.*}}) : (f32, f32, f32) -> f32
+  %0 = spirv.CL.fma %arg0, %arg1, %arg2 : f32
+  spirv.Return
+}
+
+//===----------------------------------------------------------------------===//
+// Integer OpenCL ops
+//===----------------------------------------------------------------------===//
+
+// CHECK-LABEL: @cl_integer
+spirv.func @cl_integer(%arg0: i32, %arg1: i32) "None" {
+  // CHECK: llvm.intr.smax(%{{.*}}, %{{.*}}) : (i32, i32) -> i32
+  %0 = spirv.CL.s_max %arg0, %arg1 : i32
+  // CHECK: llvm.intr.smin(%{{.*}}, %{{.*}}) : (i32, i32) -> i32
+  %1 = spirv.CL.s_min %arg0, %arg1 : i32
+  // CHECK: llvm.intr.umax(%{{.*}}, %{{.*}}) : (i32, i32) -> i32
+  %2 = spirv.CL.u_max %arg0, %arg1 : i32
+  // CHECK: llvm.intr.umin(%{{.*}}, %{{.*}}) : (i32, i32) -> i32
+  %3 = spirv.CL.u_min %arg0, %arg1 : i32
+  spirv.Return
+}

diff  --git a/mlir/test/Conversion/SPIRVToLLVM/gl-ops-to-llvm.mlir b/mlir/test/Conversion/SPIRVToLLVM/gl-ops-to-llvm.mlir
index d0079de0688ba..ffa47efbf9213 100644
--- a/mlir/test/Conversion/SPIRVToLLVM/gl-ops-to-llvm.mlir
+++ b/mlir/test/Conversion/SPIRVToLLVM/gl-ops-to-llvm.mlir
@@ -333,3 +333,31 @@ spirv.func @inverse_sqrt(%arg0: f32) "None" {
   %0 = spirv.GL.InverseSqrt %arg0 : f32
   spirv.Return
 }
+
+//===----------------------------------------------------------------------===//
+// spirv.GL.Trunc
+//===----------------------------------------------------------------------===//
+
+// CHECK-LABEL: @trunc
+spirv.func @trunc(%arg0: f32, %arg1: vector<3xf16>) "None" {
+  // CHECK: llvm.intr.trunc(%{{.*}}) : (f32) -> f32
+  %0 = spirv.GL.Trunc %arg0 : f32
+  // CHECK: llvm.intr.trunc(%{{.*}}) : (vector<3xf16>) -> vector<3xf16>
+  %1 = spirv.GL.Trunc %arg1 : vector<3xf16>
+  spirv.Return
+}
+
+//===----------------------------------------------------------------------===//
+// spirv.GL.Asin, spirv.GL.Acos, spirv.GL.Atan
+//===----------------------------------------------------------------------===//
+
+// CHECK-LABEL: @asin_acos_atan
+spirv.func @asin_acos_atan(%arg0: f32, %arg1: vector<3xf16>) "None" {
+  // CHECK: llvm.intr.asin(%{{.*}}) : (f32) -> f32
+  %0 = spirv.GL.Asin %arg0 : f32
+  // CHECK: llvm.intr.acos(%{{.*}}) : (vector<3xf16>) -> vector<3xf16>
+  %1 = spirv.GL.Acos %arg1 : vector<3xf16>
+  // CHECK: llvm.intr.atan(%{{.*}}) : (f32) -> f32
+  %2 = spirv.GL.Atan %arg0 : f32
+  spirv.Return
+}

diff  --git a/mlir/test/Conversion/SPIRVToLLVM/logical-ops-to-llvm.mlir b/mlir/test/Conversion/SPIRVToLLVM/logical-ops-to-llvm.mlir
index aab2dce980ca7..209330421997b 100644
--- a/mlir/test/Conversion/SPIRVToLLVM/logical-ops-to-llvm.mlir
+++ b/mlir/test/Conversion/SPIRVToLLVM/logical-ops-to-llvm.mlir
@@ -91,3 +91,39 @@ spirv.func @logical_or_vector(%arg0: vector<4xi1>, %arg1: vector<4xi1>) "None" {
   %0 = spirv.LogicalOr %arg0, %arg1 : vector<4xi1>
   spirv.Return
 }
+
+//===----------------------------------------------------------------------===//
+// spirv.Ordered
+//===----------------------------------------------------------------------===//
+
+// CHECK-LABEL: @ordered_scalar
+spirv.func @ordered_scalar(%arg0: f32, %arg1: f32) "None" {
+  // CHECK: llvm.fcmp "ord" %{{.*}}, %{{.*}} : f32
+  %0 = spirv.Ordered %arg0, %arg1 : f32
+  spirv.Return
+}
+
+// CHECK-LABEL: @ordered_vector
+spirv.func @ordered_vector(%arg0: vector<4xf32>, %arg1: vector<4xf32>) "None" {
+  // CHECK: llvm.fcmp "ord" %{{.*}}, %{{.*}} : vector<4xf32>
+  %0 = spirv.Ordered %arg0, %arg1 : vector<4xf32>
+  spirv.Return
+}
+
+//===----------------------------------------------------------------------===//
+// spirv.Unordered
+//===----------------------------------------------------------------------===//
+
+// CHECK-LABEL: @unordered_scalar
+spirv.func @unordered_scalar(%arg0: f32, %arg1: f32) "None" {
+  // CHECK: llvm.fcmp "uno" %{{.*}}, %{{.*}} : f32
+  %0 = spirv.Unordered %arg0, %arg1 : f32
+  spirv.Return
+}
+
+// CHECK-LABEL: @unordered_vector
+spirv.func @unordered_vector(%arg0: vector<4xf32>, %arg1: vector<4xf32>) "None" {
+  // CHECK: llvm.fcmp "uno" %{{.*}}, %{{.*}} : vector<4xf32>
+  %0 = spirv.Unordered %arg0, %arg1 : vector<4xf32>
+  spirv.Return
+}


        


More information about the llvm-branch-commits mailing list