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 +} _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
