-
Notifications
You must be signed in to change notification settings - Fork 11k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[MLIR] Enable GPU Dialect to SYCL runtime integration #71430
Changes from all commits
c76403c
47ac95e
50c621e
b4068d5
95559ef
2783bc1
e3e14f0
117ed91
59f5fdc
61f2be9
044132a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
//===- SPIRVToLLVMIRTranslation.h - SPIR-V to LLVM IR -----------*- C++ -*-===// | ||
// | ||
// 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 | ||
// | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// This provides registration calls for SPIR-V dialect to LLVM IR translation. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef MLIR_TARGET_LLVMIR_DIALECT_SPIRV_SPIRVTOLLVMIRTRANSLATION_H | ||
#define MLIR_TARGET_LLVMIR_DIALECT_SPIRV_SPIRVTOLLVMIRTRANSLATION_H | ||
|
||
namespace mlir { | ||
|
||
class DialectRegistry; | ||
class MLIRContext; | ||
|
||
/// Register the SPIR-V dialect and the translation from it to the LLVM IR in | ||
/// the given registry; | ||
void registerSPIRVDialectTranslation(DialectRegistry ®istry); | ||
|
||
/// Register the SPIR-V dialect and the translation from it in the registry | ||
/// associated with the given context. | ||
void registerSPIRVDialectTranslation(MLIRContext &context); | ||
|
||
} // namespace mlir | ||
|
||
#endif // MLIR_TARGET_LLVMIR_DIALECT_SPIRV_SPIRVTOLLVMIRTRANSLATION_H |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
add_mlir_translation_library(MLIRSPIRVToLLVMIRTranslation | ||
SPIRVToLLVMIRTranslation.cpp | ||
|
||
LINK_COMPONENTS | ||
Core | ||
|
||
LINK_LIBS PUBLIC | ||
MLIRIR | ||
MLIRLLVMDialect | ||
MLIRSPIRVDialect | ||
MLIRSupport | ||
MLIRTargetLLVMIRExport | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
//===- SPIRVToLLVMIRTranslation.cpp - Translate SPIR-V to LLVM IR ---------===// | ||
// | ||
// 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 | ||
// | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// This file implements a translation between the MLIR SPIR-V dialect and | ||
// LLVM IR. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#include "mlir/Target/LLVMIR/Dialect/SPIRV/SPIRVToLLVMIRTranslation.h" | ||
#include "mlir/Dialect/SPIRV/IR/SPIRVDialect.h" | ||
#include "mlir/IR/BuiltinAttributes.h" | ||
#include "mlir/IR/Operation.h" | ||
#include "mlir/Target/LLVMIR/ModuleTranslation.h" | ||
|
||
using namespace mlir; | ||
using namespace mlir::LLVM; | ||
|
||
void mlir::registerSPIRVDialectTranslation(DialectRegistry ®istry) { | ||
registry.insert<spirv::SPIRVDialect>(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm confused here: there is no translation interface. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is no translation but dialect registration is still required as spirv.target_env is attached and appears in input. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't quite understand why the API is called "registerSPIRVDialectTranslation" when it itself registers a dialect and no translation actually... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm sorry I missed these. I had the same concern, the alternative was adding an inline registration call. However, I then realized that adding |
||
} | ||
|
||
void mlir::registerSPIRVDialectTranslation(MLIRContext &context) { | ||
DialectRegistry registry; | ||
registerSPIRVDialectTranslation(registry); | ||
context.appendDialectRegistry(registry); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
// RUN: mlir-opt %s -pass-pipeline='builtin.module(spirv-attach-target{ver=v1.0 caps=Addresses,Int64,Kernel},convert-gpu-to-spirv{use-64bit-index=true},gpu.module(spirv.module(spirv-lower-abi-attrs,spirv-update-vce)),func.func(llvm-request-c-wrappers),convert-scf-to-cf,convert-cf-to-llvm,convert-arith-to-llvm,convert-math-to-llvm,convert-func-to-llvm,gpu-to-llvm{use-bare-pointers-for-kernels=true},gpu-module-to-binary,expand-strided-metadata,lower-affine,finalize-memref-to-llvm,reconcile-unrealized-casts)' \ | ||
// RUN: | mlir-cpu-runner \ | ||
// RUN: --shared-libs=%mlir_sycl_runtime \ | ||
// RUN: --shared-libs=%mlir_runner_utils \ | ||
// RUN: --entry-point-result=void \ | ||
// RUN: | FileCheck %s | ||
|
||
module @add attributes {gpu.container_module} { | ||
memref.global "private" constant @__constant_2x2x2xf32_0 : memref<2x2x2xf32> = dense<[[[1.1, 2.2], [3.3, 4.4]], [[5.5, 6.6], [7.7, 8.8 ]]]> | ||
memref.global "private" constant @__constant_2x2x2xf32 : memref<2x2x2xf32> = dense<[[[1.2, 2.3], [4.5, 5.8]], [[7.2, 8.3], [10.5, 11.8]]]> | ||
func.func @main() { | ||
%0 = memref.get_global @__constant_2x2x2xf32 : memref<2x2x2xf32> | ||
%1 = memref.get_global @__constant_2x2x2xf32_0 : memref<2x2x2xf32> | ||
%2 = call @test(%0, %1) : (memref<2x2x2xf32>, memref<2x2x2xf32>) -> memref<2x2x2xf32> | ||
%cast = memref.cast %2 : memref<2x2x2xf32> to memref<*xf32> | ||
call @printMemrefF32(%cast) : (memref<*xf32>) -> () | ||
return | ||
} | ||
func.func private @printMemrefF32(memref<*xf32>) | ||
func.func @test(%arg0: memref<2x2x2xf32>, %arg1: memref<2x2x2xf32>) -> memref<2x2x2xf32> { | ||
Dinistro marked this conversation as resolved.
Show resolved
Hide resolved
|
||
%c2 = arith.constant 2 : index | ||
%c1 = arith.constant 1 : index | ||
%mem = gpu.alloc host_shared () : memref<2x2x2xf32> | ||
memref.copy %arg1, %mem : memref<2x2x2xf32> to memref<2x2x2xf32> | ||
%memref_0 = gpu.alloc host_shared () : memref<2x2x2xf32> | ||
memref.copy %arg0, %memref_0 : memref<2x2x2xf32> to memref<2x2x2xf32> | ||
%memref_2 = gpu.alloc host_shared () : memref<2x2x2xf32> | ||
%2 = gpu.wait async | ||
%3 = gpu.launch_func async [%2] @test_kernel::@test_kernel blocks in (%c2, %c2, %c2) threads in (%c1, %c1, %c1) args(%memref_0 : memref<2x2x2xf32>, %mem : memref<2x2x2xf32>, %memref_2 : memref<2x2x2xf32>) | ||
gpu.wait [%3] | ||
%alloc = memref.alloc() : memref<2x2x2xf32> | ||
memref.copy %memref_2, %alloc : memref<2x2x2xf32> to memref<2x2x2xf32> | ||
%4 = gpu.wait async | ||
%5 = gpu.dealloc async [%4] %memref_2 : memref<2x2x2xf32> | ||
%6 = gpu.dealloc async [%5] %memref_0 : memref<2x2x2xf32> | ||
%7 = gpu.dealloc async [%6] %mem : memref<2x2x2xf32> | ||
gpu.wait [%7] | ||
return %alloc : memref<2x2x2xf32> | ||
} | ||
gpu.module @test_kernel attributes {spirv.target_env = #spirv.target_env<#spirv.vce<v1.0, [Addresses, Int64, Kernel], []>, api=OpenCL, #spirv.resource_limits<>>} { | ||
gpu.func @test_kernel(%arg0: memref<2x2x2xf32>, %arg1: memref<2x2x2xf32>, %arg2: memref<2x2x2xf32>) kernel attributes {gpu.known_block_size = array<i32: 1, 1, 1>, gpu.known_grid_size = array<i32: 2, 2, 2>, spirv.entry_point_abi = #spirv.entry_point_abi<>} { | ||
%0 = gpu.block_id x | ||
%1 = gpu.block_id y | ||
%2 = gpu.block_id z | ||
%3 = memref.load %arg0[%0, %1, %2] : memref<2x2x2xf32> | ||
%4 = memref.load %arg1[%0, %1, %2] : memref<2x2x2xf32> | ||
%5 = arith.addf %3, %4 : f32 | ||
memref.store %5, %arg2[%0, %1, %2] : memref<2x2x2xf32> | ||
gpu.return | ||
} | ||
} | ||
// CHECK: [2.3, 4.5] | ||
// CHECK: [7.8, 10.2] | ||
// CHECK: [12.7, 14.9] | ||
// CHECK: [18.2, 20.6] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
// RUN: mlir-opt %s -pass-pipeline='builtin.module(spirv-attach-target{ver=v1.0 caps=Addresses,Int64,Kernel},convert-gpu-to-spirv{use-64bit-index=true},gpu.module(spirv.module(spirv-lower-abi-attrs,spirv-update-vce)),func.func(llvm-request-c-wrappers),convert-scf-to-cf,convert-cf-to-llvm,convert-arith-to-llvm,convert-math-to-llvm,convert-func-to-llvm,gpu-to-llvm{use-bare-pointers-for-kernels=true},gpu-module-to-binary,expand-strided-metadata,lower-affine,finalize-memref-to-llvm,reconcile-unrealized-casts)' \ | ||
// RUN: | mlir-cpu-runner \ | ||
// RUN: --shared-libs=%mlir_sycl_runtime \ | ||
// RUN: --shared-libs=%mlir_runner_utils \ | ||
// RUN: --entry-point-result=void \ | ||
// RUN: | FileCheck %s | ||
|
||
module @add attributes {gpu.container_module} { | ||
memref.global "private" constant @__constant_3x3xi64_0 : memref<3x3xi64> = dense<[[1, 4098, 3], [16777220, 5, 4294967302], [7, 1099511627784, 9]]> | ||
memref.global "private" constant @__constant_3x3xi64 : memref<3x3xi64> = dense<[[1, 2, 3], [4, 5, 4102], [16777223, 4294967304, 1099511627785]]> | ||
func.func @main() { | ||
%0 = memref.get_global @__constant_3x3xi64 : memref<3x3xi64> | ||
%1 = memref.get_global @__constant_3x3xi64_0 : memref<3x3xi64> | ||
%2 = call @test(%0, %1) : (memref<3x3xi64>, memref<3x3xi64>) -> memref<3x3xi64> | ||
%cast = memref.cast %2 : memref<3x3xi64> to memref<*xi64> | ||
call @printMemrefI64(%cast) : (memref<*xi64>) -> () | ||
return | ||
} | ||
func.func private @printMemrefI64(memref<*xi64>) | ||
func.func @test(%arg0: memref<3x3xi64>, %arg1: memref<3x3xi64>) -> memref<3x3xi64> { | ||
%c3 = arith.constant 3 : index | ||
%c1 = arith.constant 1 : index | ||
%mem = gpu.alloc host_shared () : memref<3x3xi64> | ||
memref.copy %arg1, %mem : memref<3x3xi64> to memref<3x3xi64> | ||
%memref_0 = gpu.alloc host_shared () : memref<3x3xi64> | ||
memref.copy %arg0, %memref_0 : memref<3x3xi64> to memref<3x3xi64> | ||
%memref_2 = gpu.alloc host_shared () : memref<3x3xi64> | ||
%2 = gpu.wait async | ||
%3 = gpu.launch_func async [%2] @test_kernel::@test_kernel blocks in (%c3, %c3, %c1) threads in (%c1, %c1, %c1) args(%memref_0 : memref<3x3xi64>, %mem : memref<3x3xi64>, %memref_2 : memref<3x3xi64>) | ||
gpu.wait [%3] | ||
%alloc = memref.alloc() : memref<3x3xi64> | ||
memref.copy %memref_2, %alloc : memref<3x3xi64> to memref<3x3xi64> | ||
%4 = gpu.wait async | ||
%5 = gpu.dealloc async [%4] %memref_2 : memref<3x3xi64> | ||
%6 = gpu.dealloc async [%5] %memref_0 : memref<3x3xi64> | ||
%7 = gpu.dealloc async [%6] %mem : memref<3x3xi64> | ||
gpu.wait [%7] | ||
return %alloc : memref<3x3xi64> | ||
} | ||
gpu.module @test_kernel attributes {spirv.target_env = #spirv.target_env<#spirv.vce<v1.0, [Addresses, Int64, Kernel], []>, api=OpenCL, #spirv.resource_limits<>>} { | ||
gpu.func @test_kernel(%arg0: memref<3x3xi64>, %arg1: memref<3x3xi64>, %arg2: memref<3x3xi64>) kernel attributes {gpu.known_block_size = array<i32: 1, 1, 1>, gpu.known_grid_size = array<i32: 3, 3, 1>, spirv.entry_point_abi = #spirv.entry_point_abi<>} { | ||
%0 = gpu.block_id x | ||
%1 = gpu.block_id y | ||
%2 = memref.load %arg0[%0, %1] : memref<3x3xi64> | ||
%3 = memref.load %arg1[%0, %1] : memref<3x3xi64> | ||
%4 = arith.addi %2, %3 : i64 | ||
memref.store %4, %arg2[%0, %1] : memref<3x3xi64> | ||
gpu.return | ||
} | ||
} | ||
// CHECK: [2, 4100, 6], | ||
// CHECK: [16777224, 10, 4294971404], | ||
// CHECK: [16777230, 1103806595088, 1099511627794] | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding a full translation library for LLVM from SPIRV is not required, strictly speaking the only required change is adding here a call to
registry.insert<spirv::SPIRVDialect>();
, so thatmlir-translate
is able to load the dialect at parsing. @joker-eph thoughts on a library vs inlining the call?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@joker-eph Any thoughts on library vs inlining the call?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Trying to understand...
What is the unit test that requires this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The call to
registry.insert<spirv::SPIRVDialect>();
is needed so thatmlir-translate
can parse the code containing theSPIR-V
target attribute, nothing more; there's no translation happening from SPIR-V to LLVM. If the call is not added, thenmlir-translate
throws an error becauseSPIR-V
never gets registered.The question is, should an empty translation to LLVM be added to mirror all other * to LLVM translation code structure, or is inlining the call ok? I definitely prefer the second option -one less CMake target.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Which mlir-translate test requires that? I don't find it by skimming the patch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@silee2 can you add a test here using the GPU SPIR-V target attribute?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@fabianmcg Added test.
Any other request? The PR has been open for a while and blocking other work that depends on it. Would be great if you can approve soon.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, we were waiting on the test that you just added today!