[Mlir-commits] [mlir] [mlir][Math][XeVM] Add Math to OCL conversion patterns (PR #198370)

Akhil Goel llvmlistbot at llvm.org
Thu Jun 18 17:48:17 PDT 2026


https://github.com/akhilgoe updated https://github.com/llvm/llvm-project/pull/198370

>From df434cbcf475e43af3f9acbe88912ccaabfdfa2b Mon Sep 17 00:00:00 2001
From: Akhil Goel <akhil.goel at intel.com>
Date: Mon, 18 May 2026 01:42:10 -0700
Subject: [PATCH 1/8] Math to LLVM-SPV conversion

---
 .../Conversion/MathToLLVMSPV/MathToLLVMSPV.h  |  27 ++
 mlir/include/mlir/Conversion/Passes.h         |   1 +
 mlir/include/mlir/Conversion/Passes.td        |  22 +
 mlir/lib/Conversion/CMakeLists.txt            |   1 +
 .../GPUCommon/OpToFuncCallLowering.h          |  18 +-
 .../Conversion/MathToLLVMSPV/CMakeLists.txt   |  24 +
 .../MathToLLVMSPV/MathToLLVMSPV.cpp           | 143 ++++++
 .../MathToLLVMSPV/math-to-llvm-spv.mlir       | 414 ++++++++++++++++++
 8 files changed, 643 insertions(+), 7 deletions(-)
 create mode 100644 mlir/include/mlir/Conversion/MathToLLVMSPV/MathToLLVMSPV.h
 create mode 100644 mlir/lib/Conversion/MathToLLVMSPV/CMakeLists.txt
 create mode 100644 mlir/lib/Conversion/MathToLLVMSPV/MathToLLVMSPV.cpp
 create mode 100644 mlir/test/Conversion/MathToLLVMSPV/math-to-llvm-spv.mlir

diff --git a/mlir/include/mlir/Conversion/MathToLLVMSPV/MathToLLVMSPV.h b/mlir/include/mlir/Conversion/MathToLLVMSPV/MathToLLVMSPV.h
new file mode 100644
index 0000000000000..448b65600f930
--- /dev/null
+++ b/mlir/include/mlir/Conversion/MathToLLVMSPV/MathToLLVMSPV.h
@@ -0,0 +1,27 @@
+//===- MathToLLVMSPV.h - Utils for converting Math to LLVMSPV -------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef MLIR_CONVERSION_MATHTOLLVMSPV_MATHTOLLVMSPV_H_
+#define MLIR_CONVERSION_MATHTOLLVMSPV_MATHTOLLVMSPV_H_
+
+#include "mlir/Conversion/LLVMCommon/TypeConverter.h"
+#include "mlir/IR/PatternMatch.h"
+
+namespace mlir {
+class Pass;
+
+#define GEN_PASS_DECL_CONVERTMATHTOLLVMSPV
+#include "mlir/Conversion/Passes.h.inc"
+
+/// Populate the given list with patterns that convert from Math to OCL LLVM-SPV
+/// builtin calls.
+void populateMathToOCLExtSetLLVMSPVConversionPatterns(
+    const LLVMTypeConverter &converter, RewritePatternSet &patterns,
+    PatternBenefit benefit = 1);
+} // namespace mlir
+
+#endif // MLIR_CONVERSION_MATHTOLLVMSPV_MATHTOLLVMSPV_H_
diff --git a/mlir/include/mlir/Conversion/Passes.h b/mlir/include/mlir/Conversion/Passes.h
index a54b98004c3b6..8f6e080ad55c0 100644
--- a/mlir/include/mlir/Conversion/Passes.h
+++ b/mlir/include/mlir/Conversion/Passes.h
@@ -48,6 +48,7 @@
 #include "mlir/Conversion/MathToEmitC/MathToEmitCPass.h"
 #include "mlir/Conversion/MathToFuncs/MathToFuncs.h"
 #include "mlir/Conversion/MathToLLVM/MathToLLVM.h"
+#include "mlir/Conversion/MathToLLVMSPV/MathToLLVMSPV.h"
 #include "mlir/Conversion/MathToLibm/MathToLibm.h"
 #include "mlir/Conversion/MathToNVVM/MathToNVVM.h"
 #include "mlir/Conversion/MathToROCDL/MathToROCDL.h"
diff --git a/mlir/include/mlir/Conversion/Passes.td b/mlir/include/mlir/Conversion/Passes.td
index d401b56c7602d..548b1351fae02 100644
--- a/mlir/include/mlir/Conversion/Passes.td
+++ b/mlir/include/mlir/Conversion/Passes.td
@@ -838,6 +838,28 @@ def ConvertMathToLLVMPass : Pass<"convert-math-to-llvm"> {
   ];
 }
 
+//===----------------------------------------------------------------------===//
+// MathToLLVMSPV
+//===----------------------------------------------------------------------===//
+
+def ConvertMathToLLVMSPV : Pass<"convert-math-to-llvm-spv", "ModuleOp"> {
+  let summary = "Convert Math dialect to LLVM SPV builtin calls";
+  let description = [{
+    This pass converts supported Math ops to function calls for SPIR-V
+    math intrinsics.
+
+    The extensionSetName option specifies the instruction set chosen for
+    math op lowerings.  
+  }];
+  let dependentDialects = [
+    "func::FuncDialect",
+    "LLVM::LLVMDialect",
+    "vector::VectorDialect"];
+  let options = [Option<"extensionSetName", "extension-set-name", "std::string",
+                        /*default=*/"\"\"",
+                        "SPIR-V Extension set to use for math lowering">];
+}
+
 //===----------------------------------------------------------------------===//
 // MathToLibm
 //===----------------------------------------------------------------------===//
diff --git a/mlir/lib/Conversion/CMakeLists.txt b/mlir/lib/Conversion/CMakeLists.txt
index e17988b12cade..7a2e745a3a64c 100644
--- a/mlir/lib/Conversion/CMakeLists.txt
+++ b/mlir/lib/Conversion/CMakeLists.txt
@@ -39,6 +39,7 @@ add_subdirectory(MathToEmitC)
 add_subdirectory(MathToFuncs)
 add_subdirectory(MathToLibm)
 add_subdirectory(MathToLLVM)
+add_subdirectory(MathToLLVMSPV)
 add_subdirectory(MathToNVVM)
 add_subdirectory(MathToROCDL)
 add_subdirectory(MathToSPIRV)
diff --git a/mlir/lib/Conversion/GPUCommon/OpToFuncCallLowering.h b/mlir/lib/Conversion/GPUCommon/OpToFuncCallLowering.h
index 9f36e5c369d06..cb9b6da071839 100644
--- a/mlir/lib/Conversion/GPUCommon/OpToFuncCallLowering.h
+++ b/mlir/lib/Conversion/GPUCommon/OpToFuncCallLowering.h
@@ -54,14 +54,14 @@ using has_get_fastmath_t = decltype(std::declval<T>().getFastmath());
 template <typename SourceOp>
 struct OpToFuncCallLowering : public ConvertOpToLLVMPattern<SourceOp> {
 public:
-  explicit OpToFuncCallLowering(const LLVMTypeConverter &lowering,
-                                StringRef f32Func, StringRef f64Func,
-                                StringRef f32ApproxFunc, StringRef f16Func,
-                                StringRef i32Func = "",
-                                PatternBenefit benefit = 1)
+  explicit OpToFuncCallLowering(
+      const LLVMTypeConverter &lowering, StringRef f32Func, StringRef f64Func,
+      StringRef f32ApproxFunc, StringRef f16Func, StringRef i32Func = "",
+      PatternBenefit benefit = 1,
+      LLVM::cconv::CConv cconv = LLVM::cconv::CConv::C)
       : ConvertOpToLLVMPattern<SourceOp>(lowering, benefit), f32Func(f32Func),
         f64Func(f64Func), f32ApproxFunc(f32ApproxFunc), f16Func(f16Func),
-        i32Func(i32Func) {}
+        i32Func(i32Func), cconv(cconv) {}
 
   LogicalResult
   matchAndRewrite(SourceOp op, typename SourceOp::Adaptor adaptor,
@@ -104,6 +104,7 @@ struct OpToFuncCallLowering : public ConvertOpToLLVMPattern<SourceOp> {
     LLVMFuncOp funcOp = appendOrGetFuncOp(funcName, funcType, op);
     auto callOp =
         LLVM::CallOp::create(rewriter, op->getLoc(), funcOp, castedOperands);
+    callOp.setCConv(cconv);
 
     if (resultType == adaptor.getOperands().front().getType()) {
       rewriter.replaceOp(op, {callOp.getResult()});
@@ -171,7 +172,9 @@ struct OpToFuncCallLowering : public ConvertOpToLLVMPattern<SourceOp> {
     // location as debug info metadata inside of a function cannot be used
     // outside of that function.
     auto globalloc = op->getLoc()->findInstanceOfOrUnknown<FileLineColLoc>();
-    return LLVMFuncOp::create(b, globalloc, funcName, funcType);
+    auto newFuncOp = LLVMFuncOp::create(b, globalloc, funcName, funcType);
+    newFuncOp.setCConv(cconv);
+    return newFuncOp;
   }
 
   StringRef getFunctionName(Type type, SourceOp op) const {
@@ -202,6 +205,7 @@ struct OpToFuncCallLowering : public ConvertOpToLLVMPattern<SourceOp> {
   const std::string f32ApproxFunc;
   const std::string f16Func;
   const std::string i32Func;
+  const LLVM::cconv::CConv cconv;
 };
 
 } // namespace mlir
diff --git a/mlir/lib/Conversion/MathToLLVMSPV/CMakeLists.txt b/mlir/lib/Conversion/MathToLLVMSPV/CMakeLists.txt
new file mode 100644
index 0000000000000..34279187b1c21
--- /dev/null
+++ b/mlir/lib/Conversion/MathToLLVMSPV/CMakeLists.txt
@@ -0,0 +1,24 @@
+add_mlir_conversion_library(MLIRMathToLLVMSPV
+  MathToLLVMSPV.cpp
+
+  ADDITIONAL_HEADER_DIRS
+  ${MLIR_MAIN_INCLUDE_DIR}/mlir/Conversion/MathToLLVMSPV
+
+  DEPENDS
+  MLIRConversionPassIncGen
+
+  LINK_COMPONENTS
+  Core
+
+  LINK_LIBS PUBLIC
+  MLIRDialectUtils
+  MLIRFuncDialect
+  MLIRGPUToGPURuntimeTransforms
+  MLIRMathDialect
+  MLIRLLVMCommonConversion
+  MLIRLLVMDialect
+  MLIRPass
+  MLIRTransformUtils
+  MLIRVectorDialect
+  MLIRVectorUtils
+  )
diff --git a/mlir/lib/Conversion/MathToLLVMSPV/MathToLLVMSPV.cpp b/mlir/lib/Conversion/MathToLLVMSPV/MathToLLVMSPV.cpp
new file mode 100644
index 0000000000000..82a32b3966981
--- /dev/null
+++ b/mlir/lib/Conversion/MathToLLVMSPV/MathToLLVMSPV.cpp
@@ -0,0 +1,143 @@
+//===-- MathToLLVMSPV.cpp - conversion from Math to SPIR-V builtin calls --===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Conversion/MathToLLVMSPV/MathToLLVMSPV.h"
+#include "mlir/Dialect/Func/IR/FuncOps.h"
+#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
+#include "mlir/Dialect/Math/IR/Math.h"
+#include "mlir/Dialect/Vector/IR/VectorOps.h"
+#include "mlir/IR/BuiltinDialect.h"
+#include "mlir/Pass/Pass.h"
+
+#include "../GPUCommon/GPUOpsLowering.h"
+#include "../GPUCommon/OpToFuncCallLowering.h"
+
+namespace mlir {
+#define GEN_PASS_DEF_CONVERTMATHTOLLVMSPV
+#include "mlir/Conversion/Passes.h.inc"
+} // namespace mlir
+
+using namespace mlir;
+
+#define DEBUG_TYPE "math-to-llvm-spv"
+
+static bool isExtensionSetSupported(StringRef name) {
+  return name == "OpenCL.std";
+}
+
+template <typename OpTy>
+static void populateOpPatterns(const LLVMTypeConverter &converter,
+                               RewritePatternSet &patterns,
+                               PatternBenefit benefit, StringRef f32Func,
+                               StringRef f64Func) {
+  patterns.add<ScalarizeVectorOpLowering<OpTy>>(converter, benefit);
+  patterns.add<OpToFuncCallLowering<OpTy>>(converter, f32Func, f64Func,
+                                           /*f32ApproxFunc=*/"", /*f16Func=*/"",
+                                           /*i32Func=*/"", benefit,
+                                           LLVM::cconv::CConv::SPIR_FUNC);
+}
+
+template <typename OpTy>
+static void populateOCLExtSetOpPatterns(const LLVMTypeConverter &converter,
+                                        RewritePatternSet &patterns,
+                                        PatternBenefit benefit,
+                                        StringRef opName) {
+  std::string mangledName =
+      "_Z" + std::to_string(12 + opName.size()) + "__spirv_ocl_" + opName.str();
+  populateOpPatterns<OpTy>(converter, patterns, benefit, mangledName + "f",
+                           mangledName + "d");
+}
+
+void mlir::populateMathToOCLExtSetLLVMSPVConversionPatterns(
+    const LLVMTypeConverter &converter, RewritePatternSet &patterns,
+    PatternBenefit benefit) {
+  populateOCLExtSetOpPatterns<math::AcosOp>(converter, patterns, benefit,
+                                            "acos");
+  populateOCLExtSetOpPatterns<math::AcoshOp>(converter, patterns, benefit,
+                                             "acosh");
+  populateOCLExtSetOpPatterns<math::AsinOp>(converter, patterns, benefit,
+                                            "asin");
+  populateOCLExtSetOpPatterns<math::AsinhOp>(converter, patterns, benefit,
+                                             "asinh");
+  populateOCLExtSetOpPatterns<math::AtanOp>(converter, patterns, benefit,
+                                            "atan");
+  populateOCLExtSetOpPatterns<math::Atan2Op>(converter, patterns, benefit,
+                                             "atan2");
+  populateOCLExtSetOpPatterns<math::AtanhOp>(converter, patterns, benefit,
+                                             "atanh");
+  populateOCLExtSetOpPatterns<math::CbrtOp>(converter, patterns, benefit,
+                                            "cbrt");
+  populateOCLExtSetOpPatterns<math::CopySignOp>(converter, patterns, benefit,
+                                                "copysign");
+  populateOCLExtSetOpPatterns<math::CosOp>(converter, patterns, benefit, "cos");
+  populateOCLExtSetOpPatterns<math::CoshOp>(converter, patterns, benefit,
+                                            "cosh");
+  populateOCLExtSetOpPatterns<math::ErfOp>(converter, patterns, benefit, "erf");
+  populateOCLExtSetOpPatterns<math::ErfcOp>(converter, patterns, benefit,
+                                            "erfc");
+  populateOCLExtSetOpPatterns<math::ExpOp>(converter, patterns, benefit, "exp");
+  populateOCLExtSetOpPatterns<math::Exp2Op>(converter, patterns, benefit,
+                                            "exp2");
+  populateOCLExtSetOpPatterns<math::ExpM1Op>(converter, patterns, benefit,
+                                             "expm1");
+  populateOCLExtSetOpPatterns<math::LogOp>(converter, patterns, benefit, "log");
+  populateOCLExtSetOpPatterns<math::Log10Op>(converter, patterns, benefit,
+                                             "log10");
+  populateOCLExtSetOpPatterns<math::Log1pOp>(converter, patterns, benefit,
+                                             "log1p");
+  populateOCLExtSetOpPatterns<math::Log2Op>(converter, patterns, benefit,
+                                            "log2");
+  populateOCLExtSetOpPatterns<math::PowFOp>(converter, patterns, benefit,
+                                            "pow");
+  populateOCLExtSetOpPatterns<math::RsqrtOp>(converter, patterns, benefit,
+                                             "rsqrt");
+  populateOCLExtSetOpPatterns<math::SinOp>(converter, patterns, benefit, "sin");
+  populateOCLExtSetOpPatterns<math::SinhOp>(converter, patterns, benefit,
+                                            "sinh");
+  populateOCLExtSetOpPatterns<math::SqrtOp>(converter, patterns, benefit,
+                                            "sqrt");
+  populateOCLExtSetOpPatterns<math::TanOp>(converter, patterns, benefit, "tan");
+  populateOCLExtSetOpPatterns<math::TanhOp>(converter, patterns, benefit,
+                                            "tanh");
+}
+
+namespace {
+struct ConvertMathToLLVMSPVPass final
+    : impl::ConvertMathToLLVMSPVBase<ConvertMathToLLVMSPVPass> {
+  using impl::ConvertMathToLLVMSPVBase<
+      ConvertMathToLLVMSPVPass>::ConvertMathToLLVMSPVBase;
+
+  void runOnOperation() override;
+};
+} // namespace
+
+void ConvertMathToLLVMSPVPass::runOnOperation() {
+  auto m = getOperation();
+  MLIRContext *ctx = m.getContext();
+
+  if (!isExtensionSetSupported(extensionSetName)) {
+    m.emitError() << "Unsupported extension set '" << extensionSetName << "'!";
+    return signalPassFailure();
+  }
+
+  RewritePatternSet patterns(&getContext());
+  LowerToLLVMOptions options(ctx, DataLayout(m));
+  LLVMTypeConverter converter(ctx, options);
+  ConversionTarget target(getContext());
+  target.addLegalDialect<BuiltinDialect, func::FuncDialect,
+                         vector::VectorDialect, LLVM::LLVMDialect>();
+  if (extensionSetName == "OpenCL.std") {
+    populateMathToOCLExtSetLLVMSPVConversionPatterns(converter, patterns,
+                                                     /*benefit=*/1);
+    target
+        .addIllegalOp<LLVM::CosOp, LLVM::ExpOp, LLVM::Exp2Op, LLVM::LogOp,
+                      LLVM::Log10Op, LLVM::Log2Op, LLVM::SinOp, LLVM::SqrtOp>();
+  }
+  if (failed(applyPartialConversion(m, target, std::move(patterns))))
+    signalPassFailure();
+}
diff --git a/mlir/test/Conversion/MathToLLVMSPV/math-to-llvm-spv.mlir b/mlir/test/Conversion/MathToLLVMSPV/math-to-llvm-spv.mlir
new file mode 100644
index 0000000000000..d47927aa2b5ad
--- /dev/null
+++ b/mlir/test/Conversion/MathToLLVMSPV/math-to-llvm-spv.mlir
@@ -0,0 +1,414 @@
+// RUN: mlir-opt %s -split-input-file -convert-math-to-llvm-spv='extension-set-name=OpenCL.std' -gpu-module-to-binary | FileCheck %s 
+
+module @test_module {
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_copysignf(f32, f32) -> f32
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_atan2f(f32, f32) -> f32
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_powf(f32, f32) -> f32
+  // CHECK-LABEL: func @math_bin_f32
+  func.func @math_bin_f32(%arg_f32_1 : f32, %arg_f32_2 : f32) -> (f32, f32, f32) {
+    %result1 = math.copysign %arg_f32_1, %arg_f32_2 : f32
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_copysignf(%{{.*}}, %{{.*}}) : (f32, f32) -> f32
+    %result2 = math.atan2 %arg_f32_1, %arg_f32_2 : f32
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_atan2f(%{{.*}}, %{{.*}}) : (f32, f32) -> f32
+    %result3 = math.powf %arg_f32_1, %arg_f32_2 : f32
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_powf(%{{.*}}, %{{.*}}) : (f32, f32) -> f32
+    func.return %result1, %result2, %result3 : f32, f32, f32
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_copysignd(f64, f64) -> f64
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_atan2d(f64, f64) -> f64
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_powd(f64, f64) -> f64
+  // CHECK-LABEL: func @math_bin_f64
+  func.func @math_bin_f64(%arg_f64_1 : f64, %arg_f64_2 : f64) -> (f64, f64, f64) {
+    %result1 = math.copysign %arg_f64_1, %arg_f64_2 : f64
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_copysignd(%{{.*}}, %{{.*}}) : (f64, f64) -> f64
+    %result2 = math.atan2 %arg_f64_1, %arg_f64_2 : f64
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_atan2d(%{{.*}}, %{{.*}}) : (f64, f64) -> f64
+    %result3 = math.powf %arg_f64_1, %arg_f64_2 : f64
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_powd(%{{.*}}, %{{.*}}) : (f64, f64) -> f64
+    func.return %result1, %result2, %result3 : f64, f64, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_acosf(f32) -> f32
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_acosd(f64) -> f64
+  // CHECK-LABEL: func @math_acos
+  func.func @math_acos(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
+    %result32 = math.acos %arg_f32 : f32
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_acosf(%{{.*}}) : (f32) -> f32
+    %result64 = math.acos %arg_f64 : f64
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_acosd(%{{.*}}) : (f64) -> f64
+    func.return %result32, %result64 : f32, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_acoshf(f32) -> f32
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_acoshd(f64) -> f64
+  // CHECK-LABEL: func @math_acosh
+  func.func @math_acosh(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
+    %result32 = math.acosh %arg_f32 : f32
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_acoshf(%{{.*}}) : (f32) -> f32
+    %result64 = math.acosh %arg_f64 : f64
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_acoshd(%{{.*}}) : (f64) -> f64
+    func.return %result32, %result64 : f32, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_asinf(f32) -> f32
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_asind(f64) -> f64
+  // CHECK-LABEL: func @math_asin
+  func.func @math_asin(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
+    %result32 = math.asin %arg_f32 : f32
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_asinf(%{{.*}}) : (f32) -> f32
+    %result64 = math.asin %arg_f64 : f64
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_asind(%{{.*}}) : (f64) -> f64
+    func.return %result32, %result64 : f32, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_asinhf(f32) -> f32
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_asinhd(f64) -> f64
+  // CHECK-LABEL: func @math_asinh
+  func.func @math_asinh(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
+    %result32 = math.asinh %arg_f32 : f32
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_asinhf(%{{.*}}) : (f32) -> f32
+    %result64 = math.asinh %arg_f64 : f64
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_asinhd(%{{.*}}) : (f64) -> f64
+    func.return %result32, %result64 : f32, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_atanf(f32) -> f32
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_atand(f64) -> f64
+  // CHECK-LABEL: func @math_atan
+  func.func @math_atan(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
+    %result32 = math.atan %arg_f32 : f32
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_atanf(%{{.*}}) : (f32) -> f32
+    %result64 = math.atan %arg_f64 : f64
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_atand(%{{.*}}) : (f64) -> f64
+    func.return %result32, %result64 : f32, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_atanhf(f32) -> f32
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_atanhd(f64) -> f64
+  // CHECK-LABEL: func @math_atanh
+  func.func @math_atanh(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
+    %result32 = math.atanh %arg_f32 : f32
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_atanhf(%{{.*}}) : (f32) -> f32
+    %result64 = math.atanh %arg_f64 : f64
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_atanhd(%{{.*}}) : (f64) -> f64
+    func.return %result32, %result64 : f32, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_cbrtf(f32) -> f32
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_cbrtd(f64) -> f64
+  // CHECK-LABEL: func @math_cbrt
+  func.func @math_cbrt(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
+    %result32 = math.cbrt %arg_f32 : f32
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_cbrtf(%{{.*}}) : (f32) -> f32
+    %result64 = math.cbrt %arg_f64 : f64
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_cbrtd(%{{.*}}) : (f64) -> f64
+    func.return %result32, %result64 : f32, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_cosf(f32) -> f32
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_cosd(f64) -> f64
+  // CHECK-LABEL: func @math_cos
+  func.func @math_cos(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
+    %result32 = math.cos %arg_f32 : f32
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_cosf(%{{.*}}) : (f32) -> f32
+    %result64 = math.cos %arg_f64 : f64
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_cosd(%{{.*}}) : (f64) -> f64
+    func.return %result32, %result64 : f32, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_coshf(f32) -> f32
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_coshd(f64) -> f64
+  // CHECK-LABEL: func @math_cosh
+  func.func @math_cosh(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
+    %result32 = math.cosh %arg_f32 : f32
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_coshf(%{{.*}}) : (f32) -> f32
+    %result64 = math.cosh %arg_f64 : f64
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_coshd(%{{.*}}) : (f64) -> f64
+    func.return %result32, %result64 : f32, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_erff(f32) -> f32
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_erfd(f64) -> f64
+  // CHECK-LABEL: func @math_erf
+  func.func @math_erf(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
+    %result32 = math.erf %arg_f32 : f32
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_erff(%{{.*}}) : (f32) -> f32
+    %result64 = math.erf %arg_f64 : f64
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_erfd(%{{.*}}) : (f64) -> f64
+    func.return %result32, %result64 : f32, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_erfcf(f32) -> f32
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_erfcd(f64) -> f64
+  // CHECK-LABEL: func @math_erfc
+  func.func @math_erfc(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
+    %result32 = math.erfc %arg_f32 : f32
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_erfcf(%{{.*}}) : (f32) -> f32
+    %result64 = math.erfc %arg_f64 : f64
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_erfcd(%{{.*}}) : (f64) -> f64
+    func.return %result32, %result64 : f32, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_expf(f32) -> f32
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_expd(f64) -> f64
+  // CHECK-LABEL: func @math_exp
+  func.func @math_exp(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
+    %result32 = math.exp %arg_f32 : f32
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_expf(%{{.*}}) : (f32) -> f32
+    %result64 = math.exp %arg_f64 : f64
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_expd(%{{.*}}) : (f64) -> f64
+    func.return %result32, %result64 : f32, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_exp2f(f32) -> f32
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_exp2d(f64) -> f64
+  // CHECK-LABEL: func @math_exp2
+  func.func @math_exp2(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
+    %result32 = math.exp2 %arg_f32 : f32
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_exp2f(%{{.*}}) : (f32) -> f32
+    %result64 = math.exp2 %arg_f64 : f64
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_exp2d(%{{.*}}) : (f64) -> f64
+    func.return %result32, %result64 : f32, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_expm1f(f32) -> f32
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_expm1d(f64) -> f64
+  // CHECK-LABEL: func @math_expm1
+  func.func @math_expm1(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
+    %result32 = math.expm1 %arg_f32 : f32
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_expm1f(%{{.*}}) : (f32) -> f32
+    %result64 = math.expm1 %arg_f64 : f64
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_expm1d(%{{.*}}) : (f64) -> f64
+    func.return %result32, %result64 : f32, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_logf(f32) -> f32
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_logd(f64) -> f64
+  // CHECK-LABEL: func @math_log
+  func.func @math_log(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
+    %result32 = math.log %arg_f32 : f32
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_logf(%{{.*}}) : (f32) -> f32
+    %result64 = math.log %arg_f64 : f64
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_logd(%{{.*}}) : (f64) -> f64
+    func.return %result32, %result64 : f32, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_log10f(f32) -> f32
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_log10d(f64) -> f64
+  // CHECK-LABEL: func @math_log10
+  func.func @math_log10(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
+    %result32 = math.log10 %arg_f32 : f32
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_log10f(%{{.*}}) : (f32) -> f32
+    %result64 = math.log10 %arg_f64 : f64
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_log10d(%{{.*}}) : (f64) -> f64
+    func.return %result32, %result64 : f32, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_log1pf(f32) -> f32
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_log1pd(f64) -> f64
+  // CHECK-LABEL: func @math_log1p
+  func.func @math_log1p(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
+    %result32 = math.log1p %arg_f32 : f32
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_log1pf(%{{.*}}) : (f32) -> f32
+    %result64 = math.log1p %arg_f64 : f64
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_log1pd(%{{.*}}) : (f64) -> f64
+    func.return %result32, %result64 : f32, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_log2f(f32) -> f32
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_log2d(f64) -> f64
+  // CHECK-LABEL: func @math_log2
+  func.func @math_log2(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
+    %result32 = math.log2 %arg_f32 : f32
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_log2f(%{{.*}}) : (f32) -> f32
+    %result64 = math.log2 %arg_f64 : f64
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_log2d(%{{.*}}) : (f64) -> f64
+    func.return %result32, %result64 : f32, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_rsqrtf(f32) -> f32
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_rsqrtd(f64) -> f64
+  // CHECK-LABEL: func @math_rsqrt
+  func.func @math_rsqrt(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
+    %result32 = math.rsqrt %arg_f32 : f32
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_rsqrtf(%{{.*}}) : (f32) -> f32
+    %result64 = math.rsqrt %arg_f64 : f64
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_rsqrtd(%{{.*}}) : (f64) -> f64
+    func.return %result32, %result64 : f32, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_sinf(f32) -> f32
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_sind(f64) -> f64
+  // CHECK-LABEL: func @math_sin
+  func.func @math_sin(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
+    %result32 = math.sin %arg_f32 : f32
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_sinf(%{{.*}}) : (f32) -> f32
+    %result64 = math.sin %arg_f64 : f64
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_sind(%{{.*}}) : (f64) -> f64
+    func.return %result32, %result64 : f32, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_sinhf(f32) -> f32
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_sinhd(f64) -> f64
+  // CHECK-LABEL: func @math_sinh
+  func.func @math_sinh(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
+    %result32 = math.sinh %arg_f32 : f32
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_sinhf(%{{.*}}) : (f32) -> f32
+    %result64 = math.sinh %arg_f64 : f64
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_sinhd(%{{.*}}) : (f64) -> f64
+    func.return %result32, %result64 : f32, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_sqrtf(f32) -> f32
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_sqrtd(f64) -> f64
+  // CHECK-LABEL: func @math_sqrt
+  func.func @math_sqrt(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
+    %result32 = math.sqrt %arg_f32 : f32
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_sqrtf(%{{.*}}) : (f32) -> f32
+    %result64 = math.sqrt %arg_f64 : f64
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_sqrtd(%{{.*}}) : (f64) -> f64
+    func.return %result32, %result64 : f32, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_tanf(f32) -> f32
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_tand(f64) -> f64
+  // CHECK-LABEL: func @math_tan
+  func.func @math_tan(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
+    %result32 = math.tan %arg_f32 : f32
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_tanf(%{{.*}}) : (f32) -> f32
+    %result64 = math.tan %arg_f64 : f64
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_tand(%{{.*}}) : (f64) -> f64
+    func.return %result32, %result64 : f32, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_tanhf(f32) -> f32
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_tanhd(f64) -> f64
+  // CHECK-LABEL: func @math_tanh
+  func.func @math_tanh(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
+    %result32 = math.tanh %arg_f32 : f32
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_tanhf(%{{.*}}) : (f32) -> f32
+    %result64 = math.tanh %arg_f64 : f64
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_tanhd(%{{.*}}) : (f64) -> f64
+    func.return %result32, %result64 : f32, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_cbrtf(f32) -> f32
+  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_erfcf(f32) -> f32
+  // CHECK-LABEL: func @math_unary_16bit
+  func.func @math_unary_16bit(%arg_f16 : f16, %arg_bf16 : bf16) -> (f16, bf16) {
+    %resultf16 = math.cbrt %arg_f16 : f16
+    // CHECK: %[[F16:.+]] = llvm.fpext %{{.*}} : f16 to f32
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_cbrtf(%[[F16]]) : (f32) -> f32
+    // CHECK: llvm.fptrunc %{{.*}} : f32 to f16
+    %resultbf16 = math.erfc %arg_bf16 : bf16
+    // CHECK: %[[BF16:.+]] = llvm.fpext %{{.*}} : bf16 to f32
+    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_erfcf(%[[BF16]]) : (f32) -> f32
+    // CHECK: llvm.fptrunc %{{.*}} : f32 to bf16
+    func.return %resultf16, %resultbf16 : f16, bf16
+  }
+}

>From 64a52f2fe44c2801f67465de30feaf8ca3d8ba68 Mon Sep 17 00:00:00 2001
From: Akhil Goel <akhil.goel at intel.com>
Date: Mon, 18 May 2026 11:54:39 -0700
Subject: [PATCH 2/8] Remove unused flag from test

---
 mlir/test/Conversion/MathToLLVMSPV/math-to-llvm-spv.mlir | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mlir/test/Conversion/MathToLLVMSPV/math-to-llvm-spv.mlir b/mlir/test/Conversion/MathToLLVMSPV/math-to-llvm-spv.mlir
index d47927aa2b5ad..ee7b80a1abb8e 100644
--- a/mlir/test/Conversion/MathToLLVMSPV/math-to-llvm-spv.mlir
+++ b/mlir/test/Conversion/MathToLLVMSPV/math-to-llvm-spv.mlir
@@ -1,4 +1,4 @@
-// RUN: mlir-opt %s -split-input-file -convert-math-to-llvm-spv='extension-set-name=OpenCL.std' -gpu-module-to-binary | FileCheck %s 
+// RUN: mlir-opt %s -split-input-file -convert-math-to-llvm-spv='extension-set-name=OpenCL.std' | FileCheck %s 
 
 module @test_module {
   // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_copysignf(f32, f32) -> f32

>From 7d3734e483e342b898bb87c24e147ff89e5a6b6d Mon Sep 17 00:00:00 2001
From: Akhil Goel <akhil.goel at intel.com>
Date: Thu, 28 May 2026 09:19:20 -0700
Subject: [PATCH 3/8] Move patterns and add more tests

---
 .../GPUToLLVMSPV/GPUToLLVMSPVPass.h           |   3 +-
 .../Conversion/MathToLLVMSPV/MathToLLVMSPV.h  |  27 -
 .../mlir/Conversion/MathToXeVM/MathToXeVM.h   |   6 +
 mlir/include/mlir/Conversion/Passes.h         |   1 -
 mlir/include/mlir/Conversion/Passes.td        |  37 +-
 mlir/lib/Conversion/CMakeLists.txt            |   1 -
 .../Conversion/GPUToLLVMSPV/CMakeLists.txt    |   1 +
 .../Conversion/GPUToLLVMSPV/GPUToLLVMSPV.cpp  |   9 +-
 .../Conversion/MathToLLVMSPV/CMakeLists.txt   |  24 -
 .../MathToLLVMSPV/MathToLLVMSPV.cpp           | 143 ------
 mlir/lib/Conversion/MathToXeVM/CMakeLists.txt |   2 +
 mlir/lib/Conversion/MathToXeVM/MathToXeVM.cpp |  88 +++-
 .../gpu-to-llvm-spv-ocl-math.mlir             |  34 ++
 .../MathToLLVMSPV/math-to-llvm-spv.mlir       | 414 ---------------
 .../MathToXeVM/math-to-llvm-ocl-spv.mlir      | 471 ++++++++++++++++++
 15 files changed, 621 insertions(+), 640 deletions(-)
 delete mode 100644 mlir/include/mlir/Conversion/MathToLLVMSPV/MathToLLVMSPV.h
 delete mode 100644 mlir/lib/Conversion/MathToLLVMSPV/CMakeLists.txt
 delete mode 100644 mlir/lib/Conversion/MathToLLVMSPV/MathToLLVMSPV.cpp
 create mode 100644 mlir/test/Conversion/GPUToLLVMSPV/gpu-to-llvm-spv-ocl-math.mlir
 delete mode 100644 mlir/test/Conversion/MathToLLVMSPV/math-to-llvm-spv.mlir
 create mode 100644 mlir/test/Conversion/MathToXeVM/math-to-llvm-ocl-spv.mlir

diff --git a/mlir/include/mlir/Conversion/GPUToLLVMSPV/GPUToLLVMSPVPass.h b/mlir/include/mlir/Conversion/GPUToLLVMSPV/GPUToLLVMSPVPass.h
index 3bf30ae99f2bf..e0875f6a640d9 100644
--- a/mlir/include/mlir/Conversion/GPUToLLVMSPV/GPUToLLVMSPVPass.h
+++ b/mlir/include/mlir/Conversion/GPUToLLVMSPV/GPUToLLVMSPVPass.h
@@ -22,7 +22,8 @@ class TypeConverter;
 #include "mlir/Conversion/Passes.h.inc"
 
 void populateGpuToLLVMSPVConversionPatterns(const LLVMTypeConverter &converter,
-                                            RewritePatternSet &patterns);
+                                            RewritePatternSet &patterns,
+                                            bool convertMathToOCL = false);
 
 /// Populates memory space attribute conversion rules for lowering
 /// gpu.address_space to integer values.
diff --git a/mlir/include/mlir/Conversion/MathToLLVMSPV/MathToLLVMSPV.h b/mlir/include/mlir/Conversion/MathToLLVMSPV/MathToLLVMSPV.h
deleted file mode 100644
index 448b65600f930..0000000000000
--- a/mlir/include/mlir/Conversion/MathToLLVMSPV/MathToLLVMSPV.h
+++ /dev/null
@@ -1,27 +0,0 @@
-//===- MathToLLVMSPV.h - Utils for converting Math to LLVMSPV -------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-#ifndef MLIR_CONVERSION_MATHTOLLVMSPV_MATHTOLLVMSPV_H_
-#define MLIR_CONVERSION_MATHTOLLVMSPV_MATHTOLLVMSPV_H_
-
-#include "mlir/Conversion/LLVMCommon/TypeConverter.h"
-#include "mlir/IR/PatternMatch.h"
-
-namespace mlir {
-class Pass;
-
-#define GEN_PASS_DECL_CONVERTMATHTOLLVMSPV
-#include "mlir/Conversion/Passes.h.inc"
-
-/// Populate the given list with patterns that convert from Math to OCL LLVM-SPV
-/// builtin calls.
-void populateMathToOCLExtSetLLVMSPVConversionPatterns(
-    const LLVMTypeConverter &converter, RewritePatternSet &patterns,
-    PatternBenefit benefit = 1);
-} // namespace mlir
-
-#endif // MLIR_CONVERSION_MATHTOLLVMSPV_MATHTOLLVMSPV_H_
diff --git a/mlir/include/mlir/Conversion/MathToXeVM/MathToXeVM.h b/mlir/include/mlir/Conversion/MathToXeVM/MathToXeVM.h
index 91d3c92fd6296..004e6821ac6f3 100644
--- a/mlir/include/mlir/Conversion/MathToXeVM/MathToXeVM.h
+++ b/mlir/include/mlir/Conversion/MathToXeVM/MathToXeVM.h
@@ -22,6 +22,12 @@ class Pass;
 /// Populate the given list with patterns that convert from Math to XeVM calls.
 void populateMathToXeVMConversionPatterns(RewritePatternSet &patterns,
                                           bool convertArith);
+
+/// Populate the given list with patterns that convert from Math to OCL LLVM-SPV
+/// builtin calls.
+void populateMathToScalarOCLExtSetConversionPatterns(
+    const LLVMTypeConverter &converter, RewritePatternSet &patterns,
+    PatternBenefit benefit = 1);
 } // namespace mlir
 
 #endif // MLIR_CONVERSION_MATHTOXEVM_MATHTOXEVM_H_
diff --git a/mlir/include/mlir/Conversion/Passes.h b/mlir/include/mlir/Conversion/Passes.h
index 8f6e080ad55c0..a54b98004c3b6 100644
--- a/mlir/include/mlir/Conversion/Passes.h
+++ b/mlir/include/mlir/Conversion/Passes.h
@@ -48,7 +48,6 @@
 #include "mlir/Conversion/MathToEmitC/MathToEmitCPass.h"
 #include "mlir/Conversion/MathToFuncs/MathToFuncs.h"
 #include "mlir/Conversion/MathToLLVM/MathToLLVM.h"
-#include "mlir/Conversion/MathToLLVMSPV/MathToLLVMSPV.h"
 #include "mlir/Conversion/MathToLibm/MathToLibm.h"
 #include "mlir/Conversion/MathToNVVM/MathToNVVM.h"
 #include "mlir/Conversion/MathToROCDL/MathToROCDL.h"
diff --git a/mlir/include/mlir/Conversion/Passes.td b/mlir/include/mlir/Conversion/Passes.td
index 548b1351fae02..83b226f4b2e56 100644
--- a/mlir/include/mlir/Conversion/Passes.td
+++ b/mlir/include/mlir/Conversion/Passes.td
@@ -640,6 +640,9 @@ def ConvertGpuOpsToLLVMSPVOps : Pass<"convert-gpu-to-llvm-spv", "gpu::GPUModuleO
     Option<"use64bitIndex", "use-64bit-index",
            "bool", /*default=*/"false",
            "Use 64-bit integers to convert index types">,
+    Option<"convertMathToOCL", "convert-math-to-ocl",
+           "bool", /*default=*/"false",
+           "Convert supported Math ops to OCL intrinsics.">
   ];
 }
 
@@ -838,28 +841,6 @@ def ConvertMathToLLVMPass : Pass<"convert-math-to-llvm"> {
   ];
 }
 
-//===----------------------------------------------------------------------===//
-// MathToLLVMSPV
-//===----------------------------------------------------------------------===//
-
-def ConvertMathToLLVMSPV : Pass<"convert-math-to-llvm-spv", "ModuleOp"> {
-  let summary = "Convert Math dialect to LLVM SPV builtin calls";
-  let description = [{
-    This pass converts supported Math ops to function calls for SPIR-V
-    math intrinsics.
-
-    The extensionSetName option specifies the instruction set chosen for
-    math op lowerings.  
-  }];
-  let dependentDialects = [
-    "func::FuncDialect",
-    "LLVM::LLVMDialect",
-    "vector::VectorDialect"];
-  let options = [Option<"extensionSetName", "extension-set-name", "std::string",
-                        /*default=*/"\"\"",
-                        "SPIR-V Extension set to use for math lowering">];
-}
-
 //===----------------------------------------------------------------------===//
 // MathToLibm
 //===----------------------------------------------------------------------===//
@@ -920,11 +901,15 @@ def ConvertMathToXeVM : Pass<"convert-math-to-xevm"> {
     are typically mapped directly to native device instructions, often resulting
     in better performance. However, the precision/error of these intrinsics
     are implementation-defined, and thus math ops are only converted when they
-    have the `afn` fastmath flag enabled.
+    have the `afn` fastmath flag enabled. However, if the `convertToOCL` flag is
+    set then all supported math ops would be lowered to OpenCL math intrinsics.
   }];
-  let options = [Option<
-      "convertArith", "convert-arith", "bool", /*default=*/"true",
-      "Convert supported Arith ops (e.g. arith.divf) as well.">];
+  let options = [
+    Option<"convertArith", "convert-arith", "bool", /*default=*/"true",
+      "Convert supported Arith ops (e.g. arith.divf) as well.">,
+    Option<"convertToOCL", "convert-to-ocl", "bool", /*default=*/"false",
+      "Convert supported Math ops to OCL intrinsics.">
+  ];
   let dependentDialects = [
     "arith::ArithDialect",
     "xevm::XeVMDialect",
diff --git a/mlir/lib/Conversion/CMakeLists.txt b/mlir/lib/Conversion/CMakeLists.txt
index 7a2e745a3a64c..e17988b12cade 100644
--- a/mlir/lib/Conversion/CMakeLists.txt
+++ b/mlir/lib/Conversion/CMakeLists.txt
@@ -39,7 +39,6 @@ add_subdirectory(MathToEmitC)
 add_subdirectory(MathToFuncs)
 add_subdirectory(MathToLibm)
 add_subdirectory(MathToLLVM)
-add_subdirectory(MathToLLVMSPV)
 add_subdirectory(MathToNVVM)
 add_subdirectory(MathToROCDL)
 add_subdirectory(MathToSPIRV)
diff --git a/mlir/lib/Conversion/GPUToLLVMSPV/CMakeLists.txt b/mlir/lib/Conversion/GPUToLLVMSPV/CMakeLists.txt
index f2381c623e201..fc0bb87c2c4a6 100644
--- a/mlir/lib/Conversion/GPUToLLVMSPV/CMakeLists.txt
+++ b/mlir/lib/Conversion/GPUToLLVMSPV/CMakeLists.txt
@@ -9,5 +9,6 @@ add_mlir_conversion_library(MLIRGPUToLLVMSPV
   MLIRGPUToGPURuntimeTransforms
   MLIRLLVMCommonConversion
   MLIRLLVMDialect
+  MLIRMathToXeVM
   MLIRSPIRVAttrToLLVMConversion
 )
diff --git a/mlir/lib/Conversion/GPUToLLVMSPV/GPUToLLVMSPV.cpp b/mlir/lib/Conversion/GPUToLLVMSPV/GPUToLLVMSPV.cpp
index 5df9193cf27f1..fc271e6597af8 100644
--- a/mlir/lib/Conversion/GPUToLLVMSPV/GPUToLLVMSPV.cpp
+++ b/mlir/lib/Conversion/GPUToLLVMSPV/GPUToLLVMSPV.cpp
@@ -15,6 +15,7 @@
 #include "mlir/Conversion/LLVMCommon/LoweringOptions.h"
 #include "mlir/Conversion/LLVMCommon/Pattern.h"
 #include "mlir/Conversion/LLVMCommon/TypeConverter.h"
+#include "mlir/Conversion/MathToXeVM/MathToXeVM.h"
 #include "mlir/Conversion/SPIRVCommon/AttrToLLVMConverter.h"
 #include "mlir/Dialect/GPU/IR/GPUDialect.h"
 #include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
@@ -498,7 +499,7 @@ struct GPUToLLVMSPVConversionPass final
                         gpu::ShuffleOp, gpu::SubgroupIdOp, gpu::SubgroupSizeOp,
                         gpu::ThreadIdOp, gpu::PrintfOp>();
 
-    populateGpuToLLVMSPVConversionPatterns(converter, patterns);
+    populateGpuToLLVMSPVConversionPatterns(converter, patterns, convertMathToOCL);
     populateGpuMemorySpaceAttributeConversions(converter);
     patterns.add<GPUPrintfOpToLLVMCallLowering>(converter, /*addressSpace=*/2,
                                                 LLVM::cconv::CConv::SPIR_FUNC,
@@ -526,7 +527,8 @@ gpuAddressSpaceToOCLAddressSpace(gpu::AddressSpace addressSpace) {
 } // namespace
 
 void populateGpuToLLVMSPVConversionPatterns(
-    const LLVMTypeConverter &typeConverter, RewritePatternSet &patterns) {
+    const LLVMTypeConverter &typeConverter, RewritePatternSet &patterns,
+    bool convertMathToOCL) {
   patterns.add<GPUBarrierConversion, GPUReturnOpLowering, GPUShuffleConversion,
                GPUSubgroupOpConversion<gpu::LaneIdOp>,
                GPUSubgroupOpConversion<gpu::NumSubgroupsOp>,
@@ -553,6 +555,9 @@ void populateGpuToLLVMSPVConversionPatterns(
           /*kernelClusterSizeAttributeName=*/{}, LLVM::CConv::SPIR_KERNEL,
           LLVM::CConv::SPIR_FUNC,
           /*encodeWorkgroupAttributionsAsArguments=*/true});
+  if (convertMathToOCL) {
+    populateMathToScalarOCLExtSetConversionPatterns(typeConverter, patterns, 1);
+  }
 }
 
 void populateGpuMemorySpaceAttributeConversions(TypeConverter &typeConverter) {
diff --git a/mlir/lib/Conversion/MathToLLVMSPV/CMakeLists.txt b/mlir/lib/Conversion/MathToLLVMSPV/CMakeLists.txt
deleted file mode 100644
index 34279187b1c21..0000000000000
--- a/mlir/lib/Conversion/MathToLLVMSPV/CMakeLists.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-add_mlir_conversion_library(MLIRMathToLLVMSPV
-  MathToLLVMSPV.cpp
-
-  ADDITIONAL_HEADER_DIRS
-  ${MLIR_MAIN_INCLUDE_DIR}/mlir/Conversion/MathToLLVMSPV
-
-  DEPENDS
-  MLIRConversionPassIncGen
-
-  LINK_COMPONENTS
-  Core
-
-  LINK_LIBS PUBLIC
-  MLIRDialectUtils
-  MLIRFuncDialect
-  MLIRGPUToGPURuntimeTransforms
-  MLIRMathDialect
-  MLIRLLVMCommonConversion
-  MLIRLLVMDialect
-  MLIRPass
-  MLIRTransformUtils
-  MLIRVectorDialect
-  MLIRVectorUtils
-  )
diff --git a/mlir/lib/Conversion/MathToLLVMSPV/MathToLLVMSPV.cpp b/mlir/lib/Conversion/MathToLLVMSPV/MathToLLVMSPV.cpp
deleted file mode 100644
index 82a32b3966981..0000000000000
--- a/mlir/lib/Conversion/MathToLLVMSPV/MathToLLVMSPV.cpp
+++ /dev/null
@@ -1,143 +0,0 @@
-//===-- MathToLLVMSPV.cpp - conversion from Math to SPIR-V builtin calls --===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "mlir/Conversion/MathToLLVMSPV/MathToLLVMSPV.h"
-#include "mlir/Dialect/Func/IR/FuncOps.h"
-#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
-#include "mlir/Dialect/Math/IR/Math.h"
-#include "mlir/Dialect/Vector/IR/VectorOps.h"
-#include "mlir/IR/BuiltinDialect.h"
-#include "mlir/Pass/Pass.h"
-
-#include "../GPUCommon/GPUOpsLowering.h"
-#include "../GPUCommon/OpToFuncCallLowering.h"
-
-namespace mlir {
-#define GEN_PASS_DEF_CONVERTMATHTOLLVMSPV
-#include "mlir/Conversion/Passes.h.inc"
-} // namespace mlir
-
-using namespace mlir;
-
-#define DEBUG_TYPE "math-to-llvm-spv"
-
-static bool isExtensionSetSupported(StringRef name) {
-  return name == "OpenCL.std";
-}
-
-template <typename OpTy>
-static void populateOpPatterns(const LLVMTypeConverter &converter,
-                               RewritePatternSet &patterns,
-                               PatternBenefit benefit, StringRef f32Func,
-                               StringRef f64Func) {
-  patterns.add<ScalarizeVectorOpLowering<OpTy>>(converter, benefit);
-  patterns.add<OpToFuncCallLowering<OpTy>>(converter, f32Func, f64Func,
-                                           /*f32ApproxFunc=*/"", /*f16Func=*/"",
-                                           /*i32Func=*/"", benefit,
-                                           LLVM::cconv::CConv::SPIR_FUNC);
-}
-
-template <typename OpTy>
-static void populateOCLExtSetOpPatterns(const LLVMTypeConverter &converter,
-                                        RewritePatternSet &patterns,
-                                        PatternBenefit benefit,
-                                        StringRef opName) {
-  std::string mangledName =
-      "_Z" + std::to_string(12 + opName.size()) + "__spirv_ocl_" + opName.str();
-  populateOpPatterns<OpTy>(converter, patterns, benefit, mangledName + "f",
-                           mangledName + "d");
-}
-
-void mlir::populateMathToOCLExtSetLLVMSPVConversionPatterns(
-    const LLVMTypeConverter &converter, RewritePatternSet &patterns,
-    PatternBenefit benefit) {
-  populateOCLExtSetOpPatterns<math::AcosOp>(converter, patterns, benefit,
-                                            "acos");
-  populateOCLExtSetOpPatterns<math::AcoshOp>(converter, patterns, benefit,
-                                             "acosh");
-  populateOCLExtSetOpPatterns<math::AsinOp>(converter, patterns, benefit,
-                                            "asin");
-  populateOCLExtSetOpPatterns<math::AsinhOp>(converter, patterns, benefit,
-                                             "asinh");
-  populateOCLExtSetOpPatterns<math::AtanOp>(converter, patterns, benefit,
-                                            "atan");
-  populateOCLExtSetOpPatterns<math::Atan2Op>(converter, patterns, benefit,
-                                             "atan2");
-  populateOCLExtSetOpPatterns<math::AtanhOp>(converter, patterns, benefit,
-                                             "atanh");
-  populateOCLExtSetOpPatterns<math::CbrtOp>(converter, patterns, benefit,
-                                            "cbrt");
-  populateOCLExtSetOpPatterns<math::CopySignOp>(converter, patterns, benefit,
-                                                "copysign");
-  populateOCLExtSetOpPatterns<math::CosOp>(converter, patterns, benefit, "cos");
-  populateOCLExtSetOpPatterns<math::CoshOp>(converter, patterns, benefit,
-                                            "cosh");
-  populateOCLExtSetOpPatterns<math::ErfOp>(converter, patterns, benefit, "erf");
-  populateOCLExtSetOpPatterns<math::ErfcOp>(converter, patterns, benefit,
-                                            "erfc");
-  populateOCLExtSetOpPatterns<math::ExpOp>(converter, patterns, benefit, "exp");
-  populateOCLExtSetOpPatterns<math::Exp2Op>(converter, patterns, benefit,
-                                            "exp2");
-  populateOCLExtSetOpPatterns<math::ExpM1Op>(converter, patterns, benefit,
-                                             "expm1");
-  populateOCLExtSetOpPatterns<math::LogOp>(converter, patterns, benefit, "log");
-  populateOCLExtSetOpPatterns<math::Log10Op>(converter, patterns, benefit,
-                                             "log10");
-  populateOCLExtSetOpPatterns<math::Log1pOp>(converter, patterns, benefit,
-                                             "log1p");
-  populateOCLExtSetOpPatterns<math::Log2Op>(converter, patterns, benefit,
-                                            "log2");
-  populateOCLExtSetOpPatterns<math::PowFOp>(converter, patterns, benefit,
-                                            "pow");
-  populateOCLExtSetOpPatterns<math::RsqrtOp>(converter, patterns, benefit,
-                                             "rsqrt");
-  populateOCLExtSetOpPatterns<math::SinOp>(converter, patterns, benefit, "sin");
-  populateOCLExtSetOpPatterns<math::SinhOp>(converter, patterns, benefit,
-                                            "sinh");
-  populateOCLExtSetOpPatterns<math::SqrtOp>(converter, patterns, benefit,
-                                            "sqrt");
-  populateOCLExtSetOpPatterns<math::TanOp>(converter, patterns, benefit, "tan");
-  populateOCLExtSetOpPatterns<math::TanhOp>(converter, patterns, benefit,
-                                            "tanh");
-}
-
-namespace {
-struct ConvertMathToLLVMSPVPass final
-    : impl::ConvertMathToLLVMSPVBase<ConvertMathToLLVMSPVPass> {
-  using impl::ConvertMathToLLVMSPVBase<
-      ConvertMathToLLVMSPVPass>::ConvertMathToLLVMSPVBase;
-
-  void runOnOperation() override;
-};
-} // namespace
-
-void ConvertMathToLLVMSPVPass::runOnOperation() {
-  auto m = getOperation();
-  MLIRContext *ctx = m.getContext();
-
-  if (!isExtensionSetSupported(extensionSetName)) {
-    m.emitError() << "Unsupported extension set '" << extensionSetName << "'!";
-    return signalPassFailure();
-  }
-
-  RewritePatternSet patterns(&getContext());
-  LowerToLLVMOptions options(ctx, DataLayout(m));
-  LLVMTypeConverter converter(ctx, options);
-  ConversionTarget target(getContext());
-  target.addLegalDialect<BuiltinDialect, func::FuncDialect,
-                         vector::VectorDialect, LLVM::LLVMDialect>();
-  if (extensionSetName == "OpenCL.std") {
-    populateMathToOCLExtSetLLVMSPVConversionPatterns(converter, patterns,
-                                                     /*benefit=*/1);
-    target
-        .addIllegalOp<LLVM::CosOp, LLVM::ExpOp, LLVM::Exp2Op, LLVM::LogOp,
-                      LLVM::Log10Op, LLVM::Log2Op, LLVM::SinOp, LLVM::SqrtOp>();
-  }
-  if (failed(applyPartialConversion(m, target, std::move(patterns))))
-    signalPassFailure();
-}
diff --git a/mlir/lib/Conversion/MathToXeVM/CMakeLists.txt b/mlir/lib/Conversion/MathToXeVM/CMakeLists.txt
index 050c0ed90e383..ca6c07bddeee4 100644
--- a/mlir/lib/Conversion/MathToXeVM/CMakeLists.txt
+++ b/mlir/lib/Conversion/MathToXeVM/CMakeLists.txt
@@ -11,8 +11,10 @@ add_mlir_conversion_library(MLIRMathToXeVM
   Core
 
   LINK_LIBS PUBLIC
+  MLIRAnalysis
   MLIRArithAttrToLLVMConversion
   MLIRArithDialect
+  MLIRGPUToGPURuntimeTransforms
   MLIRLLVMCommonConversion
   MLIRLLVMDialect
   MLIRMathDialect
diff --git a/mlir/lib/Conversion/MathToXeVM/MathToXeVM.cpp b/mlir/lib/Conversion/MathToXeVM/MathToXeVM.cpp
index 0fe31d000237d..95b205d9d8a2a 100644
--- a/mlir/lib/Conversion/MathToXeVM/MathToXeVM.cpp
+++ b/mlir/lib/Conversion/MathToXeVM/MathToXeVM.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "mlir/Conversion/MathToXeVM/MathToXeVM.h"
+#include "mlir/Analysis/DataLayoutAnalysis.h"
 #include "mlir/Conversion/ArithCommon/AttrToLLVMConverter.h"
 #include "mlir/Dialect/LLVMIR/FunctionCallUtils.h"
 #include "mlir/Dialect/LLVMIR/LLVMDialect.h"
@@ -15,6 +16,9 @@
 #include "mlir/Pass/Pass.h"
 #include "llvm/Support/FormatVariadic.h"
 
+#include "../GPUCommon/GPUOpsLowering.h"
+#include "../GPUCommon/OpToFuncCallLowering.h"
+
 namespace mlir {
 #define GEN_PASS_DEF_CONVERTMATHTOXEVM
 #include "mlir/Conversion/Passes.h.inc"
@@ -119,6 +123,74 @@ struct ConvertNativeFuncPattern final : public OpConversionPattern<Op> {
   const StringRef nativeFunc;
 };
 
+template <typename OpTy>
+static void populateOCLExtSetOpPatterns(const LLVMTypeConverter &converter,
+                                        RewritePatternSet &patterns,
+                                        PatternBenefit benefit,
+                                        StringRef opName) {
+  std::string mangledName =
+      "_Z" + std::to_string(12 + opName.size()) + "__spirv_ocl_" + opName.str();
+
+  patterns.add<ScalarizeVectorOpLowering<OpTy>>(converter, benefit);
+  patterns.add<OpToFuncCallLowering<OpTy>>(
+      converter, mangledName + "f", mangledName + "d",
+      /*f32ApproxFunc=*/"", /*f16Func=*/"",
+      /*i32Func=*/"", benefit, LLVM::cconv::CConv::SPIR_FUNC);
+}
+
+void mlir::populateMathToScalarOCLExtSetConversionPatterns(
+    const LLVMTypeConverter &converter, RewritePatternSet &patterns,
+    PatternBenefit benefit) {
+  populateOCLExtSetOpPatterns<math::AcosOp>(converter, patterns, benefit,
+                                            "acos");
+  populateOCLExtSetOpPatterns<math::AcoshOp>(converter, patterns, benefit,
+                                             "acosh");
+  populateOCLExtSetOpPatterns<math::AsinOp>(converter, patterns, benefit,
+                                            "asin");
+  populateOCLExtSetOpPatterns<math::AsinhOp>(converter, patterns, benefit,
+                                             "asinh");
+  populateOCLExtSetOpPatterns<math::AtanOp>(converter, patterns, benefit,
+                                            "atan");
+  populateOCLExtSetOpPatterns<math::Atan2Op>(converter, patterns, benefit,
+                                             "atan2");
+  populateOCLExtSetOpPatterns<math::AtanhOp>(converter, patterns, benefit,
+                                             "atanh");
+  populateOCLExtSetOpPatterns<math::CbrtOp>(converter, patterns, benefit,
+                                            "cbrt");
+  populateOCLExtSetOpPatterns<math::CopySignOp>(converter, patterns, benefit,
+                                                "copysign");
+  populateOCLExtSetOpPatterns<math::CosOp>(converter, patterns, benefit, "cos");
+  populateOCLExtSetOpPatterns<math::CoshOp>(converter, patterns, benefit,
+                                            "cosh");
+  populateOCLExtSetOpPatterns<math::ErfOp>(converter, patterns, benefit, "erf");
+  populateOCLExtSetOpPatterns<math::ErfcOp>(converter, patterns, benefit,
+                                            "erfc");
+  populateOCLExtSetOpPatterns<math::ExpOp>(converter, patterns, benefit, "exp");
+  populateOCLExtSetOpPatterns<math::Exp2Op>(converter, patterns, benefit,
+                                            "exp2");
+  populateOCLExtSetOpPatterns<math::ExpM1Op>(converter, patterns, benefit,
+                                             "expm1");
+  populateOCLExtSetOpPatterns<math::LogOp>(converter, patterns, benefit, "log");
+  populateOCLExtSetOpPatterns<math::Log10Op>(converter, patterns, benefit,
+                                             "log10");
+  populateOCLExtSetOpPatterns<math::Log1pOp>(converter, patterns, benefit,
+                                             "log1p");
+  populateOCLExtSetOpPatterns<math::Log2Op>(converter, patterns, benefit,
+                                            "log2");
+  populateOCLExtSetOpPatterns<math::PowFOp>(converter, patterns, benefit,
+                                            "pow");
+  populateOCLExtSetOpPatterns<math::RsqrtOp>(converter, patterns, benefit,
+                                             "rsqrt");
+  populateOCLExtSetOpPatterns<math::SinOp>(converter, patterns, benefit, "sin");
+  populateOCLExtSetOpPatterns<math::SinhOp>(converter, patterns, benefit,
+                                            "sinh");
+  populateOCLExtSetOpPatterns<math::SqrtOp>(converter, patterns, benefit,
+                                            "sqrt");
+  populateOCLExtSetOpPatterns<math::TanOp>(converter, patterns, benefit, "tan");
+  populateOCLExtSetOpPatterns<math::TanhOp>(converter, patterns, benefit,
+                                            "tanh");
+}
+
 void mlir::populateMathToXeVMConversionPatterns(RewritePatternSet &patterns,
                                                 bool convertArith) {
   patterns.add<ConvertNativeFuncPattern<math::ExpOp>>(patterns.getContext(),
@@ -157,9 +229,23 @@ struct ConvertMathToXeVMPass
 } // namespace
 
 void ConvertMathToXeVMPass::runOnOperation() {
+  Operation *op = getOperation();
+  MLIRContext *ctx = op->getContext();
+
+  const auto &dl = getAnalysis<DataLayoutAnalysis>();
+
   RewritePatternSet patterns(&getContext());
-  populateMathToXeVMConversionPatterns(patterns, convertArith);
+  LowerToLLVMOptions options(ctx, dl.getAtOrAbove(op));
+  LLVMTypeConverter converter(ctx, options);
   ConversionTarget target(getContext());
+
+  if (convertToOCL) {
+    populateMathToScalarOCLExtSetConversionPatterns(converter, patterns, 1);
+    target
+        .addIllegalOp<LLVM::CosOp, LLVM::ExpOp, LLVM::Exp2Op, LLVM::LogOp,
+                      LLVM::Log10Op, LLVM::Log2Op, LLVM::SinOp, LLVM::SqrtOp>();
+  }
+  populateMathToXeVMConversionPatterns(patterns, convertArith);
   target.addLegalDialect<BuiltinDialect, LLVM::LLVMDialect>();
   if (failed(
           applyPartialConversion(getOperation(), target, std::move(patterns))))
diff --git a/mlir/test/Conversion/GPUToLLVMSPV/gpu-to-llvm-spv-ocl-math.mlir b/mlir/test/Conversion/GPUToLLVMSPV/gpu-to-llvm-spv-ocl-math.mlir
new file mode 100644
index 0000000000000..966010840d74f
--- /dev/null
+++ b/mlir/test/Conversion/GPUToLLVMSPV/gpu-to-llvm-spv-ocl-math.mlir
@@ -0,0 +1,34 @@
+// RUN: mlir-opt %s -convert-gpu-to-llvm-spv | FileCheck %s -check-prefixes='CHECK,CHECK-NO-OCL'
+// RUN: mlir-opt %s -convert-gpu-to-llvm-spv='convert-math-to-ocl=true' | FileCheck %s -check-prefixes='CHECK,CHECK-OCL'
+
+gpu.module @kernels {
+// CHECK-DAG:         llvm.func spir_funccc @_Z12get_local_idj(i32)
+// CHECK-OCL-DAG:     llvm.func spir_funccc @_Z17__spirv_ocl_expm1f(f32)
+// CHECK-NO-OCL-NOT:  llvm.func spir_funccc @_Z17__spirv_ocl_expm1f(f32)
+
+// CHECK-LABEL: func.func @expm1_vector
+  func.func @expm1_vector(%arg0: memref<32xvector<4xf32>>,
+                          %arg1: memref<32xvector<4xf32>>) {
+// CHECK: llvm.call spir_funccc @_Z12get_local_idj
+    %t_x = gpu.thread_id x
+// CHECK: %[[ARG0:.*]] = memref.load %arg0
+    %v = memref.load %arg0[%t_x] : memref<32xvector<4xf32>>
+// CHECK-OCL: %[[EXT_0:.*]] = llvm.extractelement %[[ARG0]]
+// CHECK-OCL: %[[VAL_0:.*]] = llvm.call spir_funccc @_Z17__spirv_ocl_expm1f(%[[EXT_0]])
+// CHECK-OCL: llvm.insertelement %[[VAL_0]]
+// CHECK-OCL: %[[EXT_1:.*]] = llvm.extractelement %[[ARG0]]
+// CHECK-OCL: %[[VAL_1:.*]] = llvm.call spir_funccc @_Z17__spirv_ocl_expm1f(%[[EXT_1]])
+// CHECK-OCL: llvm.insertelement %[[VAL_1]]
+// CHECK-OCL: %[[EXT_2:.*]] = llvm.extractelement %[[ARG0]]
+// CHECK-OCL: %[[VAL_2:.*]] = llvm.call spir_funccc @_Z17__spirv_ocl_expm1f(%[[EXT_2]])
+// CHECK-OCL: llvm.insertelement %[[VAL_2]]
+// CHECK-OCL: %[[EXT_3:.*]] = llvm.extractelement %[[ARG0]]
+// CHECK-OCL: %[[VAL_3:.*]] = llvm.call spir_funccc @_Z17__spirv_ocl_expm1f(%[[EXT_3]])
+// CHECK-OCL: %[[INS:.*]] = llvm.insertelement %[[VAL_3]]
+// CHECK-NO-OCL: %[[INS:.*]] = math.expm1 %[[ARG0]]
+    %r = math.expm1 %v : vector<4xf32>
+// CHECK: memref.store %[[INS]], %arg1
+    memref.store %r, %arg1[%t_x] : memref<32xvector<4xf32>>
+    return
+  }
+}
diff --git a/mlir/test/Conversion/MathToLLVMSPV/math-to-llvm-spv.mlir b/mlir/test/Conversion/MathToLLVMSPV/math-to-llvm-spv.mlir
deleted file mode 100644
index ee7b80a1abb8e..0000000000000
--- a/mlir/test/Conversion/MathToLLVMSPV/math-to-llvm-spv.mlir
+++ /dev/null
@@ -1,414 +0,0 @@
-// RUN: mlir-opt %s -split-input-file -convert-math-to-llvm-spv='extension-set-name=OpenCL.std' | FileCheck %s 
-
-module @test_module {
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_copysignf(f32, f32) -> f32
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_atan2f(f32, f32) -> f32
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_powf(f32, f32) -> f32
-  // CHECK-LABEL: func @math_bin_f32
-  func.func @math_bin_f32(%arg_f32_1 : f32, %arg_f32_2 : f32) -> (f32, f32, f32) {
-    %result1 = math.copysign %arg_f32_1, %arg_f32_2 : f32
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_copysignf(%{{.*}}, %{{.*}}) : (f32, f32) -> f32
-    %result2 = math.atan2 %arg_f32_1, %arg_f32_2 : f32
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_atan2f(%{{.*}}, %{{.*}}) : (f32, f32) -> f32
-    %result3 = math.powf %arg_f32_1, %arg_f32_2 : f32
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_powf(%{{.*}}, %{{.*}}) : (f32, f32) -> f32
-    func.return %result1, %result2, %result3 : f32, f32, f32
-  }
-}
-
-// -----
-
-module @test_module {
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_copysignd(f64, f64) -> f64
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_atan2d(f64, f64) -> f64
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_powd(f64, f64) -> f64
-  // CHECK-LABEL: func @math_bin_f64
-  func.func @math_bin_f64(%arg_f64_1 : f64, %arg_f64_2 : f64) -> (f64, f64, f64) {
-    %result1 = math.copysign %arg_f64_1, %arg_f64_2 : f64
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_copysignd(%{{.*}}, %{{.*}}) : (f64, f64) -> f64
-    %result2 = math.atan2 %arg_f64_1, %arg_f64_2 : f64
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_atan2d(%{{.*}}, %{{.*}}) : (f64, f64) -> f64
-    %result3 = math.powf %arg_f64_1, %arg_f64_2 : f64
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_powd(%{{.*}}, %{{.*}}) : (f64, f64) -> f64
-    func.return %result1, %result2, %result3 : f64, f64, f64
-  }
-}
-
-// -----
-
-module @test_module {
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_acosf(f32) -> f32
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_acosd(f64) -> f64
-  // CHECK-LABEL: func @math_acos
-  func.func @math_acos(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
-    %result32 = math.acos %arg_f32 : f32
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_acosf(%{{.*}}) : (f32) -> f32
-    %result64 = math.acos %arg_f64 : f64
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_acosd(%{{.*}}) : (f64) -> f64
-    func.return %result32, %result64 : f32, f64
-  }
-}
-
-// -----
-
-module @test_module {
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_acoshf(f32) -> f32
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_acoshd(f64) -> f64
-  // CHECK-LABEL: func @math_acosh
-  func.func @math_acosh(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
-    %result32 = math.acosh %arg_f32 : f32
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_acoshf(%{{.*}}) : (f32) -> f32
-    %result64 = math.acosh %arg_f64 : f64
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_acoshd(%{{.*}}) : (f64) -> f64
-    func.return %result32, %result64 : f32, f64
-  }
-}
-
-// -----
-
-module @test_module {
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_asinf(f32) -> f32
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_asind(f64) -> f64
-  // CHECK-LABEL: func @math_asin
-  func.func @math_asin(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
-    %result32 = math.asin %arg_f32 : f32
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_asinf(%{{.*}}) : (f32) -> f32
-    %result64 = math.asin %arg_f64 : f64
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_asind(%{{.*}}) : (f64) -> f64
-    func.return %result32, %result64 : f32, f64
-  }
-}
-
-// -----
-
-module @test_module {
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_asinhf(f32) -> f32
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_asinhd(f64) -> f64
-  // CHECK-LABEL: func @math_asinh
-  func.func @math_asinh(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
-    %result32 = math.asinh %arg_f32 : f32
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_asinhf(%{{.*}}) : (f32) -> f32
-    %result64 = math.asinh %arg_f64 : f64
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_asinhd(%{{.*}}) : (f64) -> f64
-    func.return %result32, %result64 : f32, f64
-  }
-}
-
-// -----
-
-module @test_module {
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_atanf(f32) -> f32
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_atand(f64) -> f64
-  // CHECK-LABEL: func @math_atan
-  func.func @math_atan(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
-    %result32 = math.atan %arg_f32 : f32
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_atanf(%{{.*}}) : (f32) -> f32
-    %result64 = math.atan %arg_f64 : f64
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_atand(%{{.*}}) : (f64) -> f64
-    func.return %result32, %result64 : f32, f64
-  }
-}
-
-// -----
-
-module @test_module {
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_atanhf(f32) -> f32
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_atanhd(f64) -> f64
-  // CHECK-LABEL: func @math_atanh
-  func.func @math_atanh(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
-    %result32 = math.atanh %arg_f32 : f32
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_atanhf(%{{.*}}) : (f32) -> f32
-    %result64 = math.atanh %arg_f64 : f64
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_atanhd(%{{.*}}) : (f64) -> f64
-    func.return %result32, %result64 : f32, f64
-  }
-}
-
-// -----
-
-module @test_module {
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_cbrtf(f32) -> f32
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_cbrtd(f64) -> f64
-  // CHECK-LABEL: func @math_cbrt
-  func.func @math_cbrt(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
-    %result32 = math.cbrt %arg_f32 : f32
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_cbrtf(%{{.*}}) : (f32) -> f32
-    %result64 = math.cbrt %arg_f64 : f64
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_cbrtd(%{{.*}}) : (f64) -> f64
-    func.return %result32, %result64 : f32, f64
-  }
-}
-
-// -----
-
-module @test_module {
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_cosf(f32) -> f32
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_cosd(f64) -> f64
-  // CHECK-LABEL: func @math_cos
-  func.func @math_cos(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
-    %result32 = math.cos %arg_f32 : f32
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_cosf(%{{.*}}) : (f32) -> f32
-    %result64 = math.cos %arg_f64 : f64
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_cosd(%{{.*}}) : (f64) -> f64
-    func.return %result32, %result64 : f32, f64
-  }
-}
-
-// -----
-
-module @test_module {
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_coshf(f32) -> f32
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_coshd(f64) -> f64
-  // CHECK-LABEL: func @math_cosh
-  func.func @math_cosh(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
-    %result32 = math.cosh %arg_f32 : f32
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_coshf(%{{.*}}) : (f32) -> f32
-    %result64 = math.cosh %arg_f64 : f64
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_coshd(%{{.*}}) : (f64) -> f64
-    func.return %result32, %result64 : f32, f64
-  }
-}
-
-// -----
-
-module @test_module {
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_erff(f32) -> f32
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_erfd(f64) -> f64
-  // CHECK-LABEL: func @math_erf
-  func.func @math_erf(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
-    %result32 = math.erf %arg_f32 : f32
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_erff(%{{.*}}) : (f32) -> f32
-    %result64 = math.erf %arg_f64 : f64
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_erfd(%{{.*}}) : (f64) -> f64
-    func.return %result32, %result64 : f32, f64
-  }
-}
-
-// -----
-
-module @test_module {
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_erfcf(f32) -> f32
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_erfcd(f64) -> f64
-  // CHECK-LABEL: func @math_erfc
-  func.func @math_erfc(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
-    %result32 = math.erfc %arg_f32 : f32
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_erfcf(%{{.*}}) : (f32) -> f32
-    %result64 = math.erfc %arg_f64 : f64
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_erfcd(%{{.*}}) : (f64) -> f64
-    func.return %result32, %result64 : f32, f64
-  }
-}
-
-// -----
-
-module @test_module {
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_expf(f32) -> f32
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_expd(f64) -> f64
-  // CHECK-LABEL: func @math_exp
-  func.func @math_exp(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
-    %result32 = math.exp %arg_f32 : f32
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_expf(%{{.*}}) : (f32) -> f32
-    %result64 = math.exp %arg_f64 : f64
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_expd(%{{.*}}) : (f64) -> f64
-    func.return %result32, %result64 : f32, f64
-  }
-}
-
-// -----
-
-module @test_module {
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_exp2f(f32) -> f32
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_exp2d(f64) -> f64
-  // CHECK-LABEL: func @math_exp2
-  func.func @math_exp2(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
-    %result32 = math.exp2 %arg_f32 : f32
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_exp2f(%{{.*}}) : (f32) -> f32
-    %result64 = math.exp2 %arg_f64 : f64
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_exp2d(%{{.*}}) : (f64) -> f64
-    func.return %result32, %result64 : f32, f64
-  }
-}
-
-// -----
-
-module @test_module {
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_expm1f(f32) -> f32
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_expm1d(f64) -> f64
-  // CHECK-LABEL: func @math_expm1
-  func.func @math_expm1(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
-    %result32 = math.expm1 %arg_f32 : f32
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_expm1f(%{{.*}}) : (f32) -> f32
-    %result64 = math.expm1 %arg_f64 : f64
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_expm1d(%{{.*}}) : (f64) -> f64
-    func.return %result32, %result64 : f32, f64
-  }
-}
-
-// -----
-
-module @test_module {
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_logf(f32) -> f32
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_logd(f64) -> f64
-  // CHECK-LABEL: func @math_log
-  func.func @math_log(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
-    %result32 = math.log %arg_f32 : f32
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_logf(%{{.*}}) : (f32) -> f32
-    %result64 = math.log %arg_f64 : f64
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_logd(%{{.*}}) : (f64) -> f64
-    func.return %result32, %result64 : f32, f64
-  }
-}
-
-// -----
-
-module @test_module {
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_log10f(f32) -> f32
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_log10d(f64) -> f64
-  // CHECK-LABEL: func @math_log10
-  func.func @math_log10(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
-    %result32 = math.log10 %arg_f32 : f32
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_log10f(%{{.*}}) : (f32) -> f32
-    %result64 = math.log10 %arg_f64 : f64
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_log10d(%{{.*}}) : (f64) -> f64
-    func.return %result32, %result64 : f32, f64
-  }
-}
-
-// -----
-
-module @test_module {
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_log1pf(f32) -> f32
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_log1pd(f64) -> f64
-  // CHECK-LABEL: func @math_log1p
-  func.func @math_log1p(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
-    %result32 = math.log1p %arg_f32 : f32
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_log1pf(%{{.*}}) : (f32) -> f32
-    %result64 = math.log1p %arg_f64 : f64
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_log1pd(%{{.*}}) : (f64) -> f64
-    func.return %result32, %result64 : f32, f64
-  }
-}
-
-// -----
-
-module @test_module {
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_log2f(f32) -> f32
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_log2d(f64) -> f64
-  // CHECK-LABEL: func @math_log2
-  func.func @math_log2(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
-    %result32 = math.log2 %arg_f32 : f32
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_log2f(%{{.*}}) : (f32) -> f32
-    %result64 = math.log2 %arg_f64 : f64
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_log2d(%{{.*}}) : (f64) -> f64
-    func.return %result32, %result64 : f32, f64
-  }
-}
-
-// -----
-
-module @test_module {
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_rsqrtf(f32) -> f32
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_rsqrtd(f64) -> f64
-  // CHECK-LABEL: func @math_rsqrt
-  func.func @math_rsqrt(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
-    %result32 = math.rsqrt %arg_f32 : f32
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_rsqrtf(%{{.*}}) : (f32) -> f32
-    %result64 = math.rsqrt %arg_f64 : f64
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_rsqrtd(%{{.*}}) : (f64) -> f64
-    func.return %result32, %result64 : f32, f64
-  }
-}
-
-// -----
-
-module @test_module {
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_sinf(f32) -> f32
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_sind(f64) -> f64
-  // CHECK-LABEL: func @math_sin
-  func.func @math_sin(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
-    %result32 = math.sin %arg_f32 : f32
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_sinf(%{{.*}}) : (f32) -> f32
-    %result64 = math.sin %arg_f64 : f64
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_sind(%{{.*}}) : (f64) -> f64
-    func.return %result32, %result64 : f32, f64
-  }
-}
-
-// -----
-
-module @test_module {
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_sinhf(f32) -> f32
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_sinhd(f64) -> f64
-  // CHECK-LABEL: func @math_sinh
-  func.func @math_sinh(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
-    %result32 = math.sinh %arg_f32 : f32
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_sinhf(%{{.*}}) : (f32) -> f32
-    %result64 = math.sinh %arg_f64 : f64
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_sinhd(%{{.*}}) : (f64) -> f64
-    func.return %result32, %result64 : f32, f64
-  }
-}
-
-// -----
-
-module @test_module {
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_sqrtf(f32) -> f32
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_sqrtd(f64) -> f64
-  // CHECK-LABEL: func @math_sqrt
-  func.func @math_sqrt(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
-    %result32 = math.sqrt %arg_f32 : f32
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_sqrtf(%{{.*}}) : (f32) -> f32
-    %result64 = math.sqrt %arg_f64 : f64
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_sqrtd(%{{.*}}) : (f64) -> f64
-    func.return %result32, %result64 : f32, f64
-  }
-}
-
-// -----
-
-module @test_module {
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_tanf(f32) -> f32
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_tand(f64) -> f64
-  // CHECK-LABEL: func @math_tan
-  func.func @math_tan(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
-    %result32 = math.tan %arg_f32 : f32
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_tanf(%{{.*}}) : (f32) -> f32
-    %result64 = math.tan %arg_f64 : f64
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_tand(%{{.*}}) : (f64) -> f64
-    func.return %result32, %result64 : f32, f64
-  }
-}
-
-// -----
-
-module @test_module {
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_tanhf(f32) -> f32
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_tanhd(f64) -> f64
-  // CHECK-LABEL: func @math_tanh
-  func.func @math_tanh(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
-    %result32 = math.tanh %arg_f32 : f32
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_tanhf(%{{.*}}) : (f32) -> f32
-    %result64 = math.tanh %arg_f64 : f64
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_tanhd(%{{.*}}) : (f64) -> f64
-    func.return %result32, %result64 : f32, f64
-  }
-}
-
-// -----
-
-module @test_module {
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_cbrtf(f32) -> f32
-  // CHECK: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_erfcf(f32) -> f32
-  // CHECK-LABEL: func @math_unary_16bit
-  func.func @math_unary_16bit(%arg_f16 : f16, %arg_bf16 : bf16) -> (f16, bf16) {
-    %resultf16 = math.cbrt %arg_f16 : f16
-    // CHECK: %[[F16:.+]] = llvm.fpext %{{.*}} : f16 to f32
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_cbrtf(%[[F16]]) : (f32) -> f32
-    // CHECK: llvm.fptrunc %{{.*}} : f32 to f16
-    %resultbf16 = math.erfc %arg_bf16 : bf16
-    // CHECK: %[[BF16:.+]] = llvm.fpext %{{.*}} : bf16 to f32
-    // CHECK: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_erfcf(%[[BF16]]) : (f32) -> f32
-    // CHECK: llvm.fptrunc %{{.*}} : f32 to bf16
-    func.return %resultf16, %resultbf16 : f16, bf16
-  }
-}
diff --git a/mlir/test/Conversion/MathToXeVM/math-to-llvm-ocl-spv.mlir b/mlir/test/Conversion/MathToXeVM/math-to-llvm-ocl-spv.mlir
new file mode 100644
index 0000000000000..ddc265e03d183
--- /dev/null
+++ b/mlir/test/Conversion/MathToXeVM/math-to-llvm-ocl-spv.mlir
@@ -0,0 +1,471 @@
+// RUN: mlir-opt %s -split-input-file -convert-math-to-xevm | FileCheck %s -check-prefixes='CHECK,CHECK-NO-OCL' 
+// RUN: mlir-opt %s -split-input-file -convert-math-to-xevm='convert-to-ocl=true' | FileCheck %s -check-prefixes='CHECK,CHECK-OCL' 
+
+module @test_module {
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_copysignf(f32, f32) -> f32
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_atan2f(f32, f32) -> f32
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_powf(f32, f32) -> f32
+  // CHECK-LABEL: func @math_bin_f32
+  func.func @math_bin_f32(%arg_f32_1 : f32, %arg_f32_2 : f32) -> (f32, f32, f32) {
+    %result1 = math.copysign %arg_f32_1, %arg_f32_2 : f32
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_copysignf(%{{.*}}, %{{.*}}) : (f32, f32) -> f32
+    // CHECK-NO-OCL: math.copysign
+    %result2 = math.atan2 %arg_f32_1, %arg_f32_2 : f32
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_atan2f(%{{.*}}, %{{.*}}) : (f32, f32) -> f32
+    // CHECK-NO-OCL: math.atan2
+    %result3 = math.powf %arg_f32_1, %arg_f32_2 : f32
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_powf(%{{.*}}, %{{.*}}) : (f32, f32) -> f32
+    // CHECK-NO-OCL: math.powf
+    func.return %result1, %result2, %result3 : f32, f32, f32
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_copysignd(f64, f64) -> f64
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_atan2d(f64, f64) -> f64
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_powd(f64, f64) -> f64
+  // CHECK-LABEL: func @math_bin_f64
+  func.func @math_bin_f64(%arg_f64_1 : f64, %arg_f64_2 : f64) -> (f64, f64, f64) {
+    %result1 = math.copysign %arg_f64_1, %arg_f64_2 : f64
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_copysignd(%{{.*}}, %{{.*}}) : (f64, f64) -> f64
+    // CHECK-NO-OCL: math.copysign
+    %result2 = math.atan2 %arg_f64_1, %arg_f64_2 : f64
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_atan2d(%{{.*}}, %{{.*}}) : (f64, f64) -> f64
+    // CHECK-NO-OCL: math.atan2
+    %result3 = math.powf %arg_f64_1, %arg_f64_2 : f64
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_powd(%{{.*}}, %{{.*}}) : (f64, f64) -> f64
+    // CHECK-NO-OCL: math.powf
+    func.return %result1, %result2, %result3 : f64, f64, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_acosf(f32) -> f32
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_acosd(f64) -> f64
+  // CHECK-LABEL: func @math_acos
+  func.func @math_acos(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
+    %result32 = math.acos %arg_f32 : f32
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_acosf(%{{.*}}) : (f32) -> f32
+    // CHECK-NO-OCL: math.acos
+    %result64 = math.acos %arg_f64 : f64
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_acosd(%{{.*}}) : (f64) -> f64
+    // CHECK-NO-OCL: math.acos
+    func.return %result32, %result64 : f32, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_acoshf(f32) -> f32
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_acoshd(f64) -> f64
+  // CHECK-LABEL: func @math_acosh
+  func.func @math_acosh(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
+    %result32 = math.acosh %arg_f32 : f32
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_acoshf(%{{.*}}) : (f32) -> f32
+    // CHECK-NO-OCL: math.acosh
+    %result64 = math.acosh %arg_f64 : f64
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_acoshd(%{{.*}}) : (f64) -> f64
+    // CHECK-NO-OCL: math.acosh
+    func.return %result32, %result64 : f32, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_asinf(f32) -> f32
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_asind(f64) -> f64
+  // CHECK-LABEL: func @math_asin
+  func.func @math_asin(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
+    %result32 = math.asin %arg_f32 : f32
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_asinf(%{{.*}}) : (f32) -> f32
+    // CHECK-NO-OCL: math.asin
+    %result64 = math.asin %arg_f64 : f64
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_asind(%{{.*}}) : (f64) -> f64
+    // CHECK-NO-OCL: math.asin
+    func.return %result32, %result64 : f32, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_asinhf(f32) -> f32
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_asinhd(f64) -> f64
+  // CHECK-LABEL: func @math_asinh
+  func.func @math_asinh(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
+    %result32 = math.asinh %arg_f32 : f32
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_asinhf(%{{.*}}) : (f32) -> f32
+    // CHECK-NO-OCL: math.asinh
+    %result64 = math.asinh %arg_f64 : f64
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_asinhd(%{{.*}}) : (f64) -> f64
+    // CHECK-NO-OCL: math.asinh
+    func.return %result32, %result64 : f32, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_atanf(f32) -> f32
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_atand(f64) -> f64
+  // CHECK-LABEL: func @math_atan
+  func.func @math_atan(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
+    %result32 = math.atan %arg_f32 : f32
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_atanf(%{{.*}}) : (f32) -> f32
+    // CHECK-NO-OCL: math.atan
+    %result64 = math.atan %arg_f64 : f64
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_atand(%{{.*}}) : (f64) -> f64
+    // CHECK-NO-OCL: math.atan
+    func.return %result32, %result64 : f32, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_atanhf(f32) -> f32
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_atanhd(f64) -> f64
+  // CHECK-LABEL: func @math_atanh
+  func.func @math_atanh(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
+    %result32 = math.atanh %arg_f32 : f32
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_atanhf(%{{.*}}) : (f32) -> f32
+    // CHECK-NO-OCL: math.atanh
+    %result64 = math.atanh %arg_f64 : f64
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_atanhd(%{{.*}}) : (f64) -> f64
+    // CHECK-NO-OCL: math.atanh
+    func.return %result32, %result64 : f32, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_cbrtf(f32) -> f32
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_cbrtd(f64) -> f64
+  // CHECK-LABEL: func @math_cbrt
+  func.func @math_cbrt(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
+    %result32 = math.cbrt %arg_f32 : f32
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_cbrtf(%{{.*}}) : (f32) -> f32
+    // CHECK-NO-OCL: math.cbrt
+    %result64 = math.cbrt %arg_f64 : f64
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_cbrtd(%{{.*}}) : (f64) -> f64
+    // CHECK-NO-OCL: math.cbrt
+    func.return %result32, %result64 : f32, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_cosf(f32) -> f32
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_cosd(f64) -> f64
+  // CHECK-LABEL: func @math_cos
+  func.func @math_cos(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
+    %result32 = math.cos %arg_f32 : f32
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_cosf(%{{.*}}) : (f32) -> f32
+    // CHECK-NO-OCL: math.cos
+    %result64 = math.cos %arg_f64 : f64
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_cosd(%{{.*}}) : (f64) -> f64
+    // CHECK-NO-OCL: math.cos
+    func.return %result32, %result64 : f32, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_coshf(f32) -> f32
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_coshd(f64) -> f64
+  // CHECK-LABEL: func @math_cosh
+  func.func @math_cosh(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
+    %result32 = math.cosh %arg_f32 : f32
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_coshf(%{{.*}}) : (f32) -> f32
+    // CHECK-NO-OCL: math.cosh
+    %result64 = math.cosh %arg_f64 : f64
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_coshd(%{{.*}}) : (f64) -> f64
+    // CHECK-NO-OCL: math.cosh
+    func.return %result32, %result64 : f32, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_erff(f32) -> f32
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_erfd(f64) -> f64
+  // CHECK-LABEL: func @math_erf
+  func.func @math_erf(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
+    %result32 = math.erf %arg_f32 : f32
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_erff(%{{.*}}) : (f32) -> f32
+    // CHECK-NO-OCL: math.erf
+    %result64 = math.erf %arg_f64 : f64
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_erfd(%{{.*}}) : (f64) -> f64
+    // CHECK-NO-OCL: math.erf
+    func.return %result32, %result64 : f32, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_erfcf(f32) -> f32
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_erfcd(f64) -> f64
+  // CHECK-LABEL: func @math_erfc
+  func.func @math_erfc(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
+    %result32 = math.erfc %arg_f32 : f32
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_erfcf(%{{.*}}) : (f32) -> f32
+    // CHECK-NO-OCL: math.erfc
+    %result64 = math.erfc %arg_f64 : f64
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_erfcd(%{{.*}}) : (f64) -> f64
+    // CHECK-NO-OCL: math.erfc
+    func.return %result32, %result64 : f32, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_expf(f32) -> f32
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_expd(f64) -> f64
+  // CHECK-LABEL: func @math_exp
+  func.func @math_exp(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
+    %result32 = math.exp %arg_f32 : f32
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_expf(%{{.*}}) : (f32) -> f32
+    // CHECK-NO-OCL: math.exp
+    %result64 = math.exp %arg_f64 : f64
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_expd(%{{.*}}) : (f64) -> f64
+    // CHECK-NO-OCL: math.exp
+    func.return %result32, %result64 : f32, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_exp2f(f32) -> f32
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_exp2d(f64) -> f64
+  // CHECK-LABEL: func @math_exp2
+  func.func @math_exp2(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
+    %result32 = math.exp2 %arg_f32 : f32
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_exp2f(%{{.*}}) : (f32) -> f32
+    // CHECK-NO-OCL: math.exp2
+    %result64 = math.exp2 %arg_f64 : f64
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_exp2d(%{{.*}}) : (f64) -> f64
+    // CHECK-NO-OCL: math.exp2
+    func.return %result32, %result64 : f32, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_expm1f(f32) -> f32
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_expm1d(f64) -> f64
+  // CHECK-LABEL: func @math_expm1
+  func.func @math_expm1(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
+    %result32 = math.expm1 %arg_f32 : f32
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_expm1f(%{{.*}}) : (f32) -> f32
+    // CHECK-NO-OCL: math.expm1
+    %result64 = math.expm1 %arg_f64 : f64
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_expm1d(%{{.*}}) : (f64) -> f64
+    // CHECK-NO-OCL: math.expm1
+    func.return %result32, %result64 : f32, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_logf(f32) -> f32
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_logd(f64) -> f64
+  // CHECK-LABEL: func @math_log
+  func.func @math_log(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
+    %result32 = math.log %arg_f32 : f32
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_logf(%{{.*}}) : (f32) -> f32
+    // CHECK-NO-OCL: math.log
+    %result64 = math.log %arg_f64 : f64
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_logd(%{{.*}}) : (f64) -> f64
+    // CHECK-NO-OCL: math.log
+    func.return %result32, %result64 : f32, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_log10f(f32) -> f32
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_log10d(f64) -> f64
+  // CHECK-LABEL: func @math_log10
+  func.func @math_log10(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
+    %result32 = math.log10 %arg_f32 : f32
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_log10f(%{{.*}}) : (f32) -> f32
+    // CHECK-NO-OCL: math.log10
+    %result64 = math.log10 %arg_f64 : f64
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_log10d(%{{.*}}) : (f64) -> f64
+    // CHECK-NO-OCL: math.log10
+    func.return %result32, %result64 : f32, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_log1pf(f32) -> f32
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_log1pd(f64) -> f64
+  // CHECK-LABEL: func @math_log1p
+  func.func @math_log1p(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
+    %result32 = math.log1p %arg_f32 : f32
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_log1pf(%{{.*}}) : (f32) -> f32
+    // CHECK-NO-OCL: math.log1p
+    %result64 = math.log1p %arg_f64 : f64
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_log1pd(%{{.*}}) : (f64) -> f64
+    // CHECK-NO-OCL: math.log1p
+    func.return %result32, %result64 : f32, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_log2f(f32) -> f32
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_log2d(f64) -> f64
+  // CHECK-LABEL: func @math_log2
+  func.func @math_log2(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
+    %result32 = math.log2 %arg_f32 : f32
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_log2f(%{{.*}}) : (f32) -> f32
+    // CHECK-NO-OCL: math.log2
+    %result64 = math.log2 %arg_f64 : f64
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_log2d(%{{.*}}) : (f64) -> f64
+    // CHECK-NO-OCL: math.log2
+    func.return %result32, %result64 : f32, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_rsqrtf(f32) -> f32
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_rsqrtd(f64) -> f64
+  // CHECK-LABEL: func @math_rsqrt
+  func.func @math_rsqrt(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
+    %result32 = math.rsqrt %arg_f32 : f32
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_rsqrtf(%{{.*}}) : (f32) -> f32
+    // CHECK-NO-OCL: math.rsqrt
+    %result64 = math.rsqrt %arg_f64 : f64
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_rsqrtd(%{{.*}}) : (f64) -> f64
+    // CHECK-NO-OCL: math.rsqrt
+    func.return %result32, %result64 : f32, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_sinf(f32) -> f32
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_sind(f64) -> f64
+  // CHECK-LABEL: func @math_sin
+  func.func @math_sin(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
+    %result32 = math.sin %arg_f32 : f32
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_sinf(%{{.*}}) : (f32) -> f32
+    // CHECK-NO-OCL: math.sin
+    %result64 = math.sin %arg_f64 : f64
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_sind(%{{.*}}) : (f64) -> f64
+    // CHECK-NO-OCL: math.sin
+    func.return %result32, %result64 : f32, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_sinhf(f32) -> f32
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_sinhd(f64) -> f64
+  // CHECK-LABEL: func @math_sinh
+  func.func @math_sinh(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
+    %result32 = math.sinh %arg_f32 : f32
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_sinhf(%{{.*}}) : (f32) -> f32
+    // CHECK-NO-OCL: math.sinh
+    %result64 = math.sinh %arg_f64 : f64
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_sinhd(%{{.*}}) : (f64) -> f64
+    // CHECK-NO-OCL: math.sinh
+    func.return %result32, %result64 : f32, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_sqrtf(f32) -> f32
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_sqrtd(f64) -> f64
+  // CHECK-LABEL: func @math_sqrt
+  func.func @math_sqrt(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
+    %result32 = math.sqrt %arg_f32 : f32
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_sqrtf(%{{.*}}) : (f32) -> f32
+    // CHECK-NO-OCL: math.sqrt
+    %result64 = math.sqrt %arg_f64 : f64
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_sqrtd(%{{.*}}) : (f64) -> f64
+    // CHECK-NO-OCL: math.sqrt
+    func.return %result32, %result64 : f32, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_tanf(f32) -> f32
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_tand(f64) -> f64
+  // CHECK-LABEL: func @math_tan
+  func.func @math_tan(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
+    %result32 = math.tan %arg_f32 : f32
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_tanf(%{{.*}}) : (f32) -> f32
+    // CHECK-NO-OCL: math.tan
+    %result64 = math.tan %arg_f64 : f64
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_tand(%{{.*}}) : (f64) -> f64
+    // CHECK-NO-OCL: math.tan
+    func.return %result32, %result64 : f32, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_tanhf(f32) -> f32
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_tanhd(f64) -> f64
+  // CHECK-LABEL: func @math_tanh
+  func.func @math_tanh(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
+    %result32 = math.tanh %arg_f32 : f32
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_tanhf(%{{.*}}) : (f32) -> f32
+    // CHECK-NO-OCL: math.tanh
+    %result64 = math.tanh %arg_f64 : f64
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_tanhd(%{{.*}}) : (f64) -> f64
+    // CHECK-NO-OCL: math.tanh
+    func.return %result32, %result64 : f32, f64
+  }
+}
+
+// -----
+
+module @test_module {
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_cbrtf(f32) -> f32
+  // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_erfcf(f32) -> f32
+  // CHECK-LABEL: func @math_unary_16bit
+  func.func @math_unary_16bit(%arg_f16 : f16, %arg_bf16 : bf16) -> (f16, bf16) {
+    %resultf16 = math.cbrt %arg_f16 : f16
+    // CHECK-OCL: %[[F16:.+]] = llvm.fpext %{{.*}} : f16 to f32
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_cbrtf(%[[F16]]) : (f32) -> f32
+    // CHECK-OCL: llvm.fptrunc %{{.*}} : f32 to f16
+    // CHECK-NO-OCL: math.cbrt
+    %resultbf16 = math.erfc %arg_bf16 : bf16
+    // CHECK-OCL: %[[BF16:.+]] = llvm.fpext %{{.*}} : bf16 to f32
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_erfcf(%[[BF16]]) : (f32) -> f32
+    // CHECK-OCL: llvm.fptrunc %{{.*}} : f32 to bf16
+    // CHECK-NO-OCL: math.erfc
+    func.return %resultf16, %resultbf16 : f16, bf16
+  }
+}

>From d4db895ac5ac2a0cc7a892ac40398ee03aec6d01 Mon Sep 17 00:00:00 2001
From: Akhil Goel <akhil.goel at intel.com>
Date: Thu, 28 May 2026 09:26:27 -0700
Subject: [PATCH 4/8] Fix formatting

---
 .../gpu-to-llvm-spv-ocl-math.mlir             | 37 +++++++++----------
 1 file changed, 18 insertions(+), 19 deletions(-)

diff --git a/mlir/test/Conversion/GPUToLLVMSPV/gpu-to-llvm-spv-ocl-math.mlir b/mlir/test/Conversion/GPUToLLVMSPV/gpu-to-llvm-spv-ocl-math.mlir
index 966010840d74f..930f387eb4205 100644
--- a/mlir/test/Conversion/GPUToLLVMSPV/gpu-to-llvm-spv-ocl-math.mlir
+++ b/mlir/test/Conversion/GPUToLLVMSPV/gpu-to-llvm-spv-ocl-math.mlir
@@ -5,30 +5,29 @@ gpu.module @kernels {
 // CHECK-DAG:         llvm.func spir_funccc @_Z12get_local_idj(i32)
 // CHECK-OCL-DAG:     llvm.func spir_funccc @_Z17__spirv_ocl_expm1f(f32)
 // CHECK-NO-OCL-NOT:  llvm.func spir_funccc @_Z17__spirv_ocl_expm1f(f32)
-
 // CHECK-LABEL: func.func @expm1_vector
   func.func @expm1_vector(%arg0: memref<32xvector<4xf32>>,
                           %arg1: memref<32xvector<4xf32>>) {
-// CHECK: llvm.call spir_funccc @_Z12get_local_idj
+    // CHECK: llvm.call spir_funccc @_Z12get_local_idj
     %t_x = gpu.thread_id x
-// CHECK: %[[ARG0:.*]] = memref.load %arg0
+    // CHECK: %[[ARG0:.*]] = memref.load %arg0
     %v = memref.load %arg0[%t_x] : memref<32xvector<4xf32>>
-// CHECK-OCL: %[[EXT_0:.*]] = llvm.extractelement %[[ARG0]]
-// CHECK-OCL: %[[VAL_0:.*]] = llvm.call spir_funccc @_Z17__spirv_ocl_expm1f(%[[EXT_0]])
-// CHECK-OCL: llvm.insertelement %[[VAL_0]]
-// CHECK-OCL: %[[EXT_1:.*]] = llvm.extractelement %[[ARG0]]
-// CHECK-OCL: %[[VAL_1:.*]] = llvm.call spir_funccc @_Z17__spirv_ocl_expm1f(%[[EXT_1]])
-// CHECK-OCL: llvm.insertelement %[[VAL_1]]
-// CHECK-OCL: %[[EXT_2:.*]] = llvm.extractelement %[[ARG0]]
-// CHECK-OCL: %[[VAL_2:.*]] = llvm.call spir_funccc @_Z17__spirv_ocl_expm1f(%[[EXT_2]])
-// CHECK-OCL: llvm.insertelement %[[VAL_2]]
-// CHECK-OCL: %[[EXT_3:.*]] = llvm.extractelement %[[ARG0]]
-// CHECK-OCL: %[[VAL_3:.*]] = llvm.call spir_funccc @_Z17__spirv_ocl_expm1f(%[[EXT_3]])
-// CHECK-OCL: %[[INS:.*]] = llvm.insertelement %[[VAL_3]]
-// CHECK-NO-OCL: %[[INS:.*]] = math.expm1 %[[ARG0]]
-    %r = math.expm1 %v : vector<4xf32>
-// CHECK: memref.store %[[INS]], %arg1
-    memref.store %r, %arg1[%t_x] : memref<32xvector<4xf32>>
+    // CHECK-OCL: %[[EXT_0:.*]] = llvm.extractelement %[[ARG0]]
+    // CHECK-OCL: %[[VAL_0:.*]] = llvm.call spir_funccc @_Z17__spirv_ocl_expm1f(%[[EXT_0]])
+    // CHECK-OCL: llvm.insertelement %[[VAL_0]]
+    // CHECK-OCL: %[[EXT_1:.*]] = llvm.extractelement %[[ARG0]]
+    // CHECK-OCL: %[[VAL_1:.*]] = llvm.call spir_funccc @_Z17__spirv_ocl_expm1f(%[[EXT_1]])
+    // CHECK-OCL: llvm.insertelement %[[VAL_1]]
+    // CHECK-OCL: %[[EXT_2:.*]] = llvm.extractelement %[[ARG0]]
+    // CHECK-OCL: %[[VAL_2:.*]] = llvm.call spir_funccc @_Z17__spirv_ocl_expm1f(%[[EXT_2]])
+    // CHECK-OCL: llvm.insertelement %[[VAL_2]]
+    // CHECK-OCL: %[[EXT_3:.*]] = llvm.extractelement %[[ARG0]]
+    // CHECK-OCL: %[[VAL_3:.*]] = llvm.call spir_funccc @_Z17__spirv_ocl_expm1f(%[[EXT_3]])
+    // CHECK-OCL: %[[INS:.*]] = llvm.insertelement %[[VAL_3]]
+    // CHECK-NO-OCL: %[[INS:.*]] = math.expm1 %[[ARG0]]
+    %e = math.expm1 %v : vector<4xf32>
+    // CHECK: memref.store %[[INS]], %arg1
+    memref.store %e, %arg1[%t_x] : memref<32xvector<4xf32>>
     return
   }
 }

>From 53fa259b9e1ee3f2420c932005889b725607f273 Mon Sep 17 00:00:00 2001
From: Akhil Goel <akhil.goel at intel.com>
Date: Thu, 28 May 2026 09:30:52 -0700
Subject: [PATCH 5/8] Fix formatting

---
 mlir/lib/Conversion/GPUToLLVMSPV/GPUToLLVMSPV.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/mlir/lib/Conversion/GPUToLLVMSPV/GPUToLLVMSPV.cpp b/mlir/lib/Conversion/GPUToLLVMSPV/GPUToLLVMSPV.cpp
index fc271e6597af8..32cfd5d5d1f72 100644
--- a/mlir/lib/Conversion/GPUToLLVMSPV/GPUToLLVMSPV.cpp
+++ b/mlir/lib/Conversion/GPUToLLVMSPV/GPUToLLVMSPV.cpp
@@ -499,7 +499,8 @@ struct GPUToLLVMSPVConversionPass final
                         gpu::ShuffleOp, gpu::SubgroupIdOp, gpu::SubgroupSizeOp,
                         gpu::ThreadIdOp, gpu::PrintfOp>();
 
-    populateGpuToLLVMSPVConversionPatterns(converter, patterns, convertMathToOCL);
+    populateGpuToLLVMSPVConversionPatterns(converter, patterns,
+                                           convertMathToOCL);
     populateGpuMemorySpaceAttributeConversions(converter);
     patterns.add<GPUPrintfOpToLLVMCallLowering>(converter, /*addressSpace=*/2,
                                                 LLVM::cconv::CConv::SPIR_FUNC,

>From c237467abba33fdd04a9ab9f29d5ba9e94c40a1d Mon Sep 17 00:00:00 2001
From: Akhil Goel <akhil.goel at intel.com>
Date: Fri, 29 May 2026 14:55:08 -0700
Subject: [PATCH 6/8] Add explicit prefix for mangled name

---
 mlir/lib/Conversion/MathToXeVM/MathToXeVM.cpp | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/mlir/lib/Conversion/MathToXeVM/MathToXeVM.cpp b/mlir/lib/Conversion/MathToXeVM/MathToXeVM.cpp
index 95b205d9d8a2a..5e2e0a54f4931 100644
--- a/mlir/lib/Conversion/MathToXeVM/MathToXeVM.cpp
+++ b/mlir/lib/Conversion/MathToXeVM/MathToXeVM.cpp
@@ -128,8 +128,10 @@ static void populateOCLExtSetOpPatterns(const LLVMTypeConverter &converter,
                                         RewritePatternSet &patterns,
                                         PatternBenefit benefit,
                                         StringRef opName) {
-  std::string mangledName =
-      "_Z" + std::to_string(12 + opName.size()) + "__spirv_ocl_" + opName.str();
+  std::string prefix = "__spirv_ocl_";
+  std::string mangledName = "_Z" +
+                            std::to_string(prefix.size() + opName.size()) +
+                            prefix + opName.str();
 
   patterns.add<ScalarizeVectorOpLowering<OpTy>>(converter, benefit);
   patterns.add<OpToFuncCallLowering<OpTy>>(

>From 18e6230f828f8ca5d7f39270e5c91fa3079bed42 Mon Sep 17 00:00:00 2001
From: Akhil Goel <akhil.goel at intel.com>
Date: Tue, 9 Jun 2026 09:27:27 -0700
Subject: [PATCH 7/8] Address review comments

---
 .../GPUToLLVMSPV/GPUToLLVMSPVPass.h           |  3 +-
 mlir/include/mlir/Conversion/Passes.td        |  3 --
 .../Conversion/GPUToLLVMSPV/CMakeLists.txt    |  1 -
 .../Conversion/GPUToLLVMSPV/GPUToLLVMSPV.cpp  | 10 +---
 .../gpu-to-llvm-spv-ocl-math.mlir             | 33 -------------
 ...-to-llvm-ocl-spv.mlir => math-to-ocl.mlir} | 49 ++++++++++++++++++-
 6 files changed, 51 insertions(+), 48 deletions(-)
 delete mode 100644 mlir/test/Conversion/GPUToLLVMSPV/gpu-to-llvm-spv-ocl-math.mlir
 rename mlir/test/Conversion/MathToXeVM/{math-to-llvm-ocl-spv.mlir => math-to-ocl.mlir} (89%)

diff --git a/mlir/include/mlir/Conversion/GPUToLLVMSPV/GPUToLLVMSPVPass.h b/mlir/include/mlir/Conversion/GPUToLLVMSPV/GPUToLLVMSPVPass.h
index e0875f6a640d9..3bf30ae99f2bf 100644
--- a/mlir/include/mlir/Conversion/GPUToLLVMSPV/GPUToLLVMSPVPass.h
+++ b/mlir/include/mlir/Conversion/GPUToLLVMSPV/GPUToLLVMSPVPass.h
@@ -22,8 +22,7 @@ class TypeConverter;
 #include "mlir/Conversion/Passes.h.inc"
 
 void populateGpuToLLVMSPVConversionPatterns(const LLVMTypeConverter &converter,
-                                            RewritePatternSet &patterns,
-                                            bool convertMathToOCL = false);
+                                            RewritePatternSet &patterns);
 
 /// Populates memory space attribute conversion rules for lowering
 /// gpu.address_space to integer values.
diff --git a/mlir/include/mlir/Conversion/Passes.td b/mlir/include/mlir/Conversion/Passes.td
index 83b226f4b2e56..3d1b4611ab2cb 100644
--- a/mlir/include/mlir/Conversion/Passes.td
+++ b/mlir/include/mlir/Conversion/Passes.td
@@ -640,9 +640,6 @@ def ConvertGpuOpsToLLVMSPVOps : Pass<"convert-gpu-to-llvm-spv", "gpu::GPUModuleO
     Option<"use64bitIndex", "use-64bit-index",
            "bool", /*default=*/"false",
            "Use 64-bit integers to convert index types">,
-    Option<"convertMathToOCL", "convert-math-to-ocl",
-           "bool", /*default=*/"false",
-           "Convert supported Math ops to OCL intrinsics.">
   ];
 }
 
diff --git a/mlir/lib/Conversion/GPUToLLVMSPV/CMakeLists.txt b/mlir/lib/Conversion/GPUToLLVMSPV/CMakeLists.txt
index fc0bb87c2c4a6..f2381c623e201 100644
--- a/mlir/lib/Conversion/GPUToLLVMSPV/CMakeLists.txt
+++ b/mlir/lib/Conversion/GPUToLLVMSPV/CMakeLists.txt
@@ -9,6 +9,5 @@ add_mlir_conversion_library(MLIRGPUToLLVMSPV
   MLIRGPUToGPURuntimeTransforms
   MLIRLLVMCommonConversion
   MLIRLLVMDialect
-  MLIRMathToXeVM
   MLIRSPIRVAttrToLLVMConversion
 )
diff --git a/mlir/lib/Conversion/GPUToLLVMSPV/GPUToLLVMSPV.cpp b/mlir/lib/Conversion/GPUToLLVMSPV/GPUToLLVMSPV.cpp
index 32cfd5d5d1f72..5df9193cf27f1 100644
--- a/mlir/lib/Conversion/GPUToLLVMSPV/GPUToLLVMSPV.cpp
+++ b/mlir/lib/Conversion/GPUToLLVMSPV/GPUToLLVMSPV.cpp
@@ -15,7 +15,6 @@
 #include "mlir/Conversion/LLVMCommon/LoweringOptions.h"
 #include "mlir/Conversion/LLVMCommon/Pattern.h"
 #include "mlir/Conversion/LLVMCommon/TypeConverter.h"
-#include "mlir/Conversion/MathToXeVM/MathToXeVM.h"
 #include "mlir/Conversion/SPIRVCommon/AttrToLLVMConverter.h"
 #include "mlir/Dialect/GPU/IR/GPUDialect.h"
 #include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
@@ -499,8 +498,7 @@ struct GPUToLLVMSPVConversionPass final
                         gpu::ShuffleOp, gpu::SubgroupIdOp, gpu::SubgroupSizeOp,
                         gpu::ThreadIdOp, gpu::PrintfOp>();
 
-    populateGpuToLLVMSPVConversionPatterns(converter, patterns,
-                                           convertMathToOCL);
+    populateGpuToLLVMSPVConversionPatterns(converter, patterns);
     populateGpuMemorySpaceAttributeConversions(converter);
     patterns.add<GPUPrintfOpToLLVMCallLowering>(converter, /*addressSpace=*/2,
                                                 LLVM::cconv::CConv::SPIR_FUNC,
@@ -528,8 +526,7 @@ gpuAddressSpaceToOCLAddressSpace(gpu::AddressSpace addressSpace) {
 } // namespace
 
 void populateGpuToLLVMSPVConversionPatterns(
-    const LLVMTypeConverter &typeConverter, RewritePatternSet &patterns,
-    bool convertMathToOCL) {
+    const LLVMTypeConverter &typeConverter, RewritePatternSet &patterns) {
   patterns.add<GPUBarrierConversion, GPUReturnOpLowering, GPUShuffleConversion,
                GPUSubgroupOpConversion<gpu::LaneIdOp>,
                GPUSubgroupOpConversion<gpu::NumSubgroupsOp>,
@@ -556,9 +553,6 @@ void populateGpuToLLVMSPVConversionPatterns(
           /*kernelClusterSizeAttributeName=*/{}, LLVM::CConv::SPIR_KERNEL,
           LLVM::CConv::SPIR_FUNC,
           /*encodeWorkgroupAttributionsAsArguments=*/true});
-  if (convertMathToOCL) {
-    populateMathToScalarOCLExtSetConversionPatterns(typeConverter, patterns, 1);
-  }
 }
 
 void populateGpuMemorySpaceAttributeConversions(TypeConverter &typeConverter) {
diff --git a/mlir/test/Conversion/GPUToLLVMSPV/gpu-to-llvm-spv-ocl-math.mlir b/mlir/test/Conversion/GPUToLLVMSPV/gpu-to-llvm-spv-ocl-math.mlir
deleted file mode 100644
index 930f387eb4205..0000000000000
--- a/mlir/test/Conversion/GPUToLLVMSPV/gpu-to-llvm-spv-ocl-math.mlir
+++ /dev/null
@@ -1,33 +0,0 @@
-// RUN: mlir-opt %s -convert-gpu-to-llvm-spv | FileCheck %s -check-prefixes='CHECK,CHECK-NO-OCL'
-// RUN: mlir-opt %s -convert-gpu-to-llvm-spv='convert-math-to-ocl=true' | FileCheck %s -check-prefixes='CHECK,CHECK-OCL'
-
-gpu.module @kernels {
-// CHECK-DAG:         llvm.func spir_funccc @_Z12get_local_idj(i32)
-// CHECK-OCL-DAG:     llvm.func spir_funccc @_Z17__spirv_ocl_expm1f(f32)
-// CHECK-NO-OCL-NOT:  llvm.func spir_funccc @_Z17__spirv_ocl_expm1f(f32)
-// CHECK-LABEL: func.func @expm1_vector
-  func.func @expm1_vector(%arg0: memref<32xvector<4xf32>>,
-                          %arg1: memref<32xvector<4xf32>>) {
-    // CHECK: llvm.call spir_funccc @_Z12get_local_idj
-    %t_x = gpu.thread_id x
-    // CHECK: %[[ARG0:.*]] = memref.load %arg0
-    %v = memref.load %arg0[%t_x] : memref<32xvector<4xf32>>
-    // CHECK-OCL: %[[EXT_0:.*]] = llvm.extractelement %[[ARG0]]
-    // CHECK-OCL: %[[VAL_0:.*]] = llvm.call spir_funccc @_Z17__spirv_ocl_expm1f(%[[EXT_0]])
-    // CHECK-OCL: llvm.insertelement %[[VAL_0]]
-    // CHECK-OCL: %[[EXT_1:.*]] = llvm.extractelement %[[ARG0]]
-    // CHECK-OCL: %[[VAL_1:.*]] = llvm.call spir_funccc @_Z17__spirv_ocl_expm1f(%[[EXT_1]])
-    // CHECK-OCL: llvm.insertelement %[[VAL_1]]
-    // CHECK-OCL: %[[EXT_2:.*]] = llvm.extractelement %[[ARG0]]
-    // CHECK-OCL: %[[VAL_2:.*]] = llvm.call spir_funccc @_Z17__spirv_ocl_expm1f(%[[EXT_2]])
-    // CHECK-OCL: llvm.insertelement %[[VAL_2]]
-    // CHECK-OCL: %[[EXT_3:.*]] = llvm.extractelement %[[ARG0]]
-    // CHECK-OCL: %[[VAL_3:.*]] = llvm.call spir_funccc @_Z17__spirv_ocl_expm1f(%[[EXT_3]])
-    // CHECK-OCL: %[[INS:.*]] = llvm.insertelement %[[VAL_3]]
-    // CHECK-NO-OCL: %[[INS:.*]] = math.expm1 %[[ARG0]]
-    %e = math.expm1 %v : vector<4xf32>
-    // CHECK: memref.store %[[INS]], %arg1
-    memref.store %e, %arg1[%t_x] : memref<32xvector<4xf32>>
-    return
-  }
-}
diff --git a/mlir/test/Conversion/MathToXeVM/math-to-llvm-ocl-spv.mlir b/mlir/test/Conversion/MathToXeVM/math-to-ocl.mlir
similarity index 89%
rename from mlir/test/Conversion/MathToXeVM/math-to-llvm-ocl-spv.mlir
rename to mlir/test/Conversion/MathToXeVM/math-to-ocl.mlir
index ddc265e03d183..6fdca2bbfd661 100644
--- a/mlir/test/Conversion/MathToXeVM/math-to-llvm-ocl-spv.mlir
+++ b/mlir/test/Conversion/MathToXeVM/math-to-ocl.mlir
@@ -1,5 +1,5 @@
 // RUN: mlir-opt %s -split-input-file -convert-math-to-xevm | FileCheck %s -check-prefixes='CHECK,CHECK-NO-OCL' 
-// RUN: mlir-opt %s -split-input-file -convert-math-to-xevm='convert-to-ocl=true' | FileCheck %s -check-prefixes='CHECK,CHECK-OCL' 
+// RUN: mlir-opt %s -split-input-file -convert-math-to-xevm='convert-to-ocl=true convert-arith=true' | FileCheck %s -check-prefixes='CHECK,CHECK-OCL' 
 
 module @test_module {
   // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_copysignf(f32, f32) -> f32
@@ -43,6 +43,37 @@ module @test_module {
 
 // -----
 
+module @test_module {
+// CHECK-OCL-DAG:     llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_expm1f(f32)
+// CHECK-NO-OCL-NOT:  llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_expm1f(f32)
+// CHECK-LABEL: func.func @expm1_vector
+  func.func @expm1_vector(%arg0: memref<32xvector<4xf32>>,
+                          %arg1: memref<32xvector<4xf32>>,
+                          %idx : index) {
+    // CHECK: %[[ARG0:.*]] = memref.load %arg0
+    %v = memref.load %arg0[%idx] : memref<32xvector<4xf32>>
+    // CHECK-OCL: %[[EXT_0:.*]] = llvm.extractelement %[[ARG0]]
+    // CHECK-OCL: %[[VAL_0:.*]] = llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_expm1f(%[[EXT_0]])
+    // CHECK-OCL: llvm.insertelement %[[VAL_0]]
+    // CHECK-OCL: %[[EXT_1:.*]] = llvm.extractelement %[[ARG0]]
+    // CHECK-OCL: %[[VAL_1:.*]] = llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_expm1f(%[[EXT_1]])
+    // CHECK-OCL: llvm.insertelement %[[VAL_1]]
+    // CHECK-OCL: %[[EXT_2:.*]] = llvm.extractelement %[[ARG0]]
+    // CHECK-OCL: %[[VAL_2:.*]] = llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_expm1f(%[[EXT_2]])
+    // CHECK-OCL: llvm.insertelement %[[VAL_2]]
+    // CHECK-OCL: %[[EXT_3:.*]] = llvm.extractelement %[[ARG0]]
+    // CHECK-OCL: %[[VAL_3:.*]] = llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_expm1f(%[[EXT_3]])
+    // CHECK-OCL: %[[INS:.*]] = llvm.insertelement %[[VAL_3]]
+    // CHECK-NO-OCL: %[[INS:.*]] = math.expm1 %[[ARG0]]
+    %e = math.expm1 %v : vector<4xf32>
+    // CHECK: memref.store %[[INS]], %arg1
+    memref.store %e, %arg1[%idx] : memref<32xvector<4xf32>>
+    return
+  }
+}
+
+// -----
+
 module @test_module {
   // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_acosf(f32) -> f32
   // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_acosd(f64) -> f64
@@ -469,3 +500,19 @@ module @test_module {
     func.return %resultf16, %resultbf16 : f16, bf16
   }
 }
+
+// -----
+
+module @test_module {
+  // CHECK-DAG: llvm.func @_Z{{.*}}__spirv_ocl_native_divideff(f32, f32) -> f32
+  // CHECK-OCL-DAG: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_sqrtf(f32) -> f32
+  // CHECK-LABEL: func @math_sqrt_div
+  func.func @math_sqrt_div(%arg : f32) -> f32 {
+    %sqrt = math.sqrt %arg : f32
+    // CHECK-OCL: llvm.call spir_funccc @_Z{{.*}}__spirv_ocl_sqrtf(%{{.*}}) : (f32) -> f32
+    // CHECK-NO-OCL: math.sqrt
+    %result = arith.divf %arg, %sqrt fastmath<afn> : f32
+    // CHECK: llvm.call @_Z{{.*}}__spirv_ocl_native_divideff(%{{.*}}) {fastmathFlags = #llvm.fastmath<afn>} : (f32, f32) -> f32
+    func.return %result : f32
+  }
+}

>From ac0e7e1383cfced5c05286366f09d0bb377fba6f Mon Sep 17 00:00:00 2001
From: Akhil Goel <akhil.goel at intel.com>
Date: Thu, 18 Jun 2026 17:52:15 -0700
Subject: [PATCH 8/8] Reverse pattern population order

---
 .../mlir/Conversion/MathToXeVM/MathToXeVM.h   |  3 +-
 mlir/lib/Conversion/MathToXeVM/MathToXeVM.cpp | 42 ++++++++++---------
 .../Conversion/MathToXeVM/math-to-ocl.mlir    | 15 +++++++
 3 files changed, 40 insertions(+), 20 deletions(-)

diff --git a/mlir/include/mlir/Conversion/MathToXeVM/MathToXeVM.h b/mlir/include/mlir/Conversion/MathToXeVM/MathToXeVM.h
index 004e6821ac6f3..1bc6b095f9ad0 100644
--- a/mlir/include/mlir/Conversion/MathToXeVM/MathToXeVM.h
+++ b/mlir/include/mlir/Conversion/MathToXeVM/MathToXeVM.h
@@ -21,7 +21,8 @@ class Pass;
 
 /// Populate the given list with patterns that convert from Math to XeVM calls.
 void populateMathToXeVMConversionPatterns(RewritePatternSet &patterns,
-                                          bool convertArith);
+                                          bool convertArith,
+                                          PatternBenefit benefit = 1);
 
 /// Populate the given list with patterns that convert from Math to OCL LLVM-SPV
 /// builtin calls.
diff --git a/mlir/lib/Conversion/MathToXeVM/MathToXeVM.cpp b/mlir/lib/Conversion/MathToXeVM/MathToXeVM.cpp
index 5e2e0a54f4931..4ced4a83a628f 100644
--- a/mlir/lib/Conversion/MathToXeVM/MathToXeVM.cpp
+++ b/mlir/lib/Conversion/MathToXeVM/MathToXeVM.cpp
@@ -194,32 +194,33 @@ void mlir::populateMathToScalarOCLExtSetConversionPatterns(
 }
 
 void mlir::populateMathToXeVMConversionPatterns(RewritePatternSet &patterns,
-                                                bool convertArith) {
-  patterns.add<ConvertNativeFuncPattern<math::ExpOp>>(patterns.getContext(),
-                                                      "__spirv_ocl_native_exp");
-  patterns.add<ConvertNativeFuncPattern<math::CosOp>>(patterns.getContext(),
-                                                      "__spirv_ocl_native_cos");
+                                                bool convertArith,
+                                                PatternBenefit benefit) {
+  patterns.add<ConvertNativeFuncPattern<math::ExpOp>>(
+      patterns.getContext(), "__spirv_ocl_native_exp", benefit);
+  patterns.add<ConvertNativeFuncPattern<math::CosOp>>(
+      patterns.getContext(), "__spirv_ocl_native_cos", benefit);
   patterns.add<ConvertNativeFuncPattern<math::Exp2Op>>(
-      patterns.getContext(), "__spirv_ocl_native_exp2");
-  patterns.add<ConvertNativeFuncPattern<math::LogOp>>(patterns.getContext(),
-                                                      "__spirv_ocl_native_log");
+      patterns.getContext(), "__spirv_ocl_native_exp2", benefit);
+  patterns.add<ConvertNativeFuncPattern<math::LogOp>>(
+      patterns.getContext(), "__spirv_ocl_native_log", benefit);
   patterns.add<ConvertNativeFuncPattern<math::Log2Op>>(
-      patterns.getContext(), "__spirv_ocl_native_log2");
+      patterns.getContext(), "__spirv_ocl_native_log2", benefit);
   patterns.add<ConvertNativeFuncPattern<math::Log10Op>>(
-      patterns.getContext(), "__spirv_ocl_native_log10");
+      patterns.getContext(), "__spirv_ocl_native_log10", benefit);
   patterns.add<ConvertNativeFuncPattern<math::PowFOp>>(
-      patterns.getContext(), "__spirv_ocl_native_powr");
+      patterns.getContext(), "__spirv_ocl_native_powr", benefit);
   patterns.add<ConvertNativeFuncPattern<math::RsqrtOp>>(
-      patterns.getContext(), "__spirv_ocl_native_rsqrt");
-  patterns.add<ConvertNativeFuncPattern<math::SinOp>>(patterns.getContext(),
-                                                      "__spirv_ocl_native_sin");
+      patterns.getContext(), "__spirv_ocl_native_rsqrt", benefit);
+  patterns.add<ConvertNativeFuncPattern<math::SinOp>>(
+      patterns.getContext(), "__spirv_ocl_native_sin", benefit);
   patterns.add<ConvertNativeFuncPattern<math::SqrtOp>>(
-      patterns.getContext(), "__spirv_ocl_native_sqrt");
-  patterns.add<ConvertNativeFuncPattern<math::TanOp>>(patterns.getContext(),
-                                                      "__spirv_ocl_native_tan");
+      patterns.getContext(), "__spirv_ocl_native_sqrt", benefit);
+  patterns.add<ConvertNativeFuncPattern<math::TanOp>>(
+      patterns.getContext(), "__spirv_ocl_native_tan", benefit);
   if (convertArith)
     patterns.add<ConvertNativeFuncPattern<arith::DivFOp>>(
-        patterns.getContext(), "__spirv_ocl_native_divide");
+        patterns.getContext(), "__spirv_ocl_native_divide", benefit);
 }
 
 namespace {
@@ -241,13 +242,16 @@ void ConvertMathToXeVMPass::runOnOperation() {
   LLVMTypeConverter converter(ctx, options);
   ConversionTarget target(getContext());
 
+  // Native OCL patterns should take precedence for `fast` ops even when
+  // convertToOCL is set.
+  populateMathToXeVMConversionPatterns(patterns, convertArith,
+                                       convertToOCL + 1);
   if (convertToOCL) {
     populateMathToScalarOCLExtSetConversionPatterns(converter, patterns, 1);
     target
         .addIllegalOp<LLVM::CosOp, LLVM::ExpOp, LLVM::Exp2Op, LLVM::LogOp,
                       LLVM::Log10Op, LLVM::Log2Op, LLVM::SinOp, LLVM::SqrtOp>();
   }
-  populateMathToXeVMConversionPatterns(patterns, convertArith);
   target.addLegalDialect<BuiltinDialect, LLVM::LLVMDialect>();
   if (failed(
           applyPartialConversion(getOperation(), target, std::move(patterns))))
diff --git a/mlir/test/Conversion/MathToXeVM/math-to-ocl.mlir b/mlir/test/Conversion/MathToXeVM/math-to-ocl.mlir
index 6fdca2bbfd661..61efa3515657e 100644
--- a/mlir/test/Conversion/MathToXeVM/math-to-ocl.mlir
+++ b/mlir/test/Conversion/MathToXeVM/math-to-ocl.mlir
@@ -74,6 +74,21 @@ module @test_module {
 
 // -----
 
+module @test_module {
+  // CHECK-DAG: llvm.func @_Z{{.*}}__spirv_ocl_native_sinf(f32) -> f32
+  // CHECK-DAG: llvm.func @_Z{{.*}}__spirv_ocl_native_sind(f64) -> f64
+  // CHECK-LABEL: func @math_fast_sin
+  func.func @math_fast_sin(%arg_f32 : f32, %arg_f64 : f64) -> (f32, f64) {
+    %result32 = math.sin %arg_f32 fastmath<afn> : f32
+    // CHECK: llvm.call @_Z{{.*}}__spirv_ocl_native_sinf(%{{.*}}) {fastmathFlags = #llvm.fastmath<afn>} : (f32) -> f32
+    %result64 = math.sin %arg_f64 fastmath<afn> : f64
+    // CHECK: llvm.call @_Z{{.*}}__spirv_ocl_native_sind(%{{.*}}) {fastmathFlags = #llvm.fastmath<afn>} : (f64) -> f64
+    func.return %result32, %result64 : f32, f64
+  }
+}
+
+// -----
+
 module @test_module {
   // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_acosf(f32) -> f32
   // CHECK-OCL: llvm.func spir_funccc @_Z{{.*}}__spirv_ocl_acosd(f64) -> f64



More information about the Mlir-commits mailing list