[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