Skip to content

Commit cf0e30a

Browse files
committed
Add XeVM to LLVMIR translation.
1 parent d2361e4 commit cf0e30a

File tree

7 files changed

+266
-0
lines changed

7 files changed

+266
-0
lines changed

mlir/include/mlir/Target/LLVMIR/Dialect/All.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "mlir/Target/LLVMIR/Dialect/ROCDL/ROCDLToLLVMIRTranslation.h"
2929
#include "mlir/Target/LLVMIR/Dialect/SPIRV/SPIRVToLLVMIRTranslation.h"
3030
#include "mlir/Target/LLVMIR/Dialect/VCIX/VCIXToLLVMIRTranslation.h"
31+
#include "mlir/Target/LLVMIR/Dialect/XeVM/XeVMToLLVMIRTranslation.h"
3132

3233
namespace mlir {
3334
class DialectRegistry;
@@ -47,6 +48,7 @@ static inline void registerAllToLLVMIRTranslations(DialectRegistry &registry) {
4748
registerROCDLDialectTranslation(registry);
4849
registerSPIRVDialectTranslation(registry);
4950
registerVCIXDialectTranslation(registry);
51+
registerXeVMDialectTranslation(registry);
5052

5153
// Extension required for translating GPU offloading Ops.
5254
gpu::registerOffloadingLLVMTranslationInterfaceExternalModels(registry);
@@ -63,6 +65,7 @@ registerAllGPUToLLVMIRTranslations(DialectRegistry &registry) {
6365
registerNVVMDialectTranslation(registry);
6466
registerROCDLDialectTranslation(registry);
6567
registerSPIRVDialectTranslation(registry);
68+
registerXeVMDialectTranslation(registry);
6669

6770
// Extension required for translating GPU offloading Ops.
6871
gpu::registerOffloadingLLVMTranslationInterfaceExternalModels(registry);
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//===-- XeVMToLLVMIRTranslation.h - XeVM to LLVM IR -------------*- C++ -*-===//
2+
//
3+
// This file is licensed under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This provides registration calls for XeVM dialect to LLVM IR translation.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef MLIR_TARGET_LLVMIR_DIALECT_XEVM_XEVMTOLLVMIRTRANSLATION_H
14+
#define MLIR_TARGET_LLVMIR_DIALECT_XEVM_XEVMTOLLVMIRTRANSLATION_H
15+
16+
namespace mlir {
17+
18+
class DialectRegistry;
19+
class MLIRContext;
20+
21+
/// Register the XeVM dialect and the translation from it to the LLVM IR in the
22+
/// given registry;
23+
void registerXeVMDialectTranslation(mlir::DialectRegistry &registry);
24+
25+
/// Register the XeVM dialect and the translation from it in the registry
26+
/// associated with the given context.
27+
void registerXeVMDialectTranslation(mlir::MLIRContext &context);
28+
29+
} // namespace mlir
30+
31+
#endif // MLIR_TARGET_LLVMIR_DIALECT_XEVM_XEVMTOLLVMIRTRANSLATION_H

mlir/lib/Target/LLVMIR/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ add_mlir_translation_library(MLIRToLLVMIRTranslationRegistration
6060
MLIRROCDLToLLVMIRTranslation
6161
MLIRSPIRVToLLVMIRTranslation
6262
MLIRVCIXToLLVMIRTranslation
63+
MLIRXeVMToLLVMIRTranslation
6364
)
6465

6566
add_mlir_translation_library(MLIRTargetLLVMIRImport

mlir/lib/Target/LLVMIR/Dialect/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ add_subdirectory(OpenMP)
1010
add_subdirectory(ROCDL)
1111
add_subdirectory(SPIRV)
1212
add_subdirectory(VCIX)
13+
add_subdirectory(XeVM)
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
set(LLVM_OPTIONAL_SOURCES
2+
XeVMToLLVMIRTranslation.cpp
3+
)
4+
5+
add_mlir_translation_library(MLIRXeVMToLLVMIRTranslation
6+
XeVMToLLVMIRTranslation.cpp
7+
8+
DEPENDS
9+
MLIRXeVMConversionsIncGen
10+
11+
LINK_COMPONENTS
12+
Core
13+
14+
LINK_LIBS PUBLIC
15+
MLIRDialectUtils
16+
MLIRIR
17+
MLIRLLVMDialect
18+
MLIRXeVMDialect
19+
MLIRSupport
20+
MLIRTargetLLVMIRExport
21+
)
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
//===-- XeVMToLLVMIRTranslation.cpp - Translate XeVM to LLVM IR -*- C++ -*-===//
2+
//
3+
// This file is licensed under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file implements a translation between the MLIR XeVM dialect and
10+
// LLVM IR.
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
#include "mlir/Target/LLVMIR/Dialect/XeVM/XeVMToLLVMIRTranslation.h"
15+
#include "mlir/Dialect/LLVMIR/XeVMDialect.h"
16+
#include "mlir/IR/BuiltinAttributes.h"
17+
#include "mlir/IR/Operation.h"
18+
#include "mlir/Target/LLVMIR/ModuleTranslation.h"
19+
20+
#include "llvm/ADT/TypeSwitch.h"
21+
#include "llvm/IR/Constants.h"
22+
#include "llvm/IR/LLVMContext.h"
23+
#include "llvm/IR/Metadata.h"
24+
25+
#include "llvm/IR/ConstantRange.h"
26+
#include "llvm/IR/IRBuilder.h"
27+
#include "llvm/Support/raw_ostream.h"
28+
29+
using namespace mlir;
30+
using namespace mlir::LLVM;
31+
32+
namespace {
33+
/// Implementation of the dialect interface that converts operations belonging
34+
/// to the XeVM dialect to LLVM IR.
35+
class XeVMDialectLLVMIRTranslationInterface
36+
: public LLVMTranslationDialectInterface {
37+
public:
38+
using LLVMTranslationDialectInterface::LLVMTranslationDialectInterface;
39+
40+
/// Attaches module-level metadata for functions marked as kernels.
41+
LogicalResult
42+
amendOperation(Operation *op, ArrayRef<llvm::Instruction *> instructions,
43+
NamedAttribute attribute,
44+
LLVM::ModuleTranslation &moduleTranslation) const final {
45+
StringRef attrName = attribute.getName().getValue();
46+
if (attrName == mlir::xevm::XeVMDialect::getCacheControlsAttrName()) {
47+
auto cacheControlsArray = dyn_cast<ArrayAttr>(attribute.getValue());
48+
if (cacheControlsArray.size() != 2) {
49+
return op->emitOpError(
50+
"Expected both L1 and L3 cache control attributes!");
51+
}
52+
if (instructions.size() != 1) {
53+
return op->emitOpError("Expecting a single instruction");
54+
}
55+
return handleDecorationCacheControl(instructions.front(),
56+
cacheControlsArray.getValue());
57+
}
58+
auto func = dyn_cast<LLVM::LLVMFuncOp>(op);
59+
if (!func)
60+
return failure();
61+
62+
return success();
63+
}
64+
65+
private:
66+
template <typename IntTy>
67+
static llvm::Metadata *getConstantIntMD(llvm::Type *type, IntTy val) {
68+
return llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(type, val));
69+
}
70+
71+
static LogicalResult handleDecorationCacheControl(llvm::Instruction *inst,
72+
ArrayRef<Attribute> attrs) {
73+
SmallVector<llvm::Metadata *> decorations;
74+
llvm::LLVMContext &ctx = inst->getContext();
75+
llvm::Type *i32Ty = llvm::IntegerType::getInt32Ty(ctx);
76+
llvm::transform(
77+
attrs, std::back_inserter(decorations),
78+
[&ctx, i32Ty](Attribute attr) -> llvm::Metadata * {
79+
auto valuesArray = dyn_cast<ArrayAttr>(attr).getValue();
80+
std::array<llvm::Metadata *, 4> metadata;
81+
llvm::transform(
82+
valuesArray, metadata.begin(), [i32Ty](Attribute valueAttr) {
83+
return llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
84+
i32Ty, cast<IntegerAttr>(valueAttr).getValue()));
85+
});
86+
return llvm::MDNode::get(ctx, metadata);
87+
});
88+
constexpr llvm::StringLiteral decorationCacheControlMDName =
89+
"spirv.DecorationCacheControlINTEL";
90+
inst->setMetadata(decorationCacheControlMDName,
91+
llvm::MDNode::get(ctx, decorations));
92+
return success();
93+
}
94+
};
95+
} // namespace
96+
97+
void ::mlir::registerXeVMDialectTranslation(::mlir::DialectRegistry &registry) {
98+
registry.insert<xevm::XeVMDialect>();
99+
registry.addExtension(+[](MLIRContext *ctx, xevm::XeVMDialect *dialect) {
100+
dialect->addInterfaces<XeVMDialectLLVMIRTranslationInterface>();
101+
});
102+
}
103+
104+
void ::mlir::registerXeVMDialectTranslation(::mlir::MLIRContext &context) {
105+
DialectRegistry registry;
106+
registerXeVMDialectTranslation(registry);
107+
context.appendDialectRegistry(registry);
108+
}

mlir/test/Target/LLVMIR/xevm.mlir

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
// RUN: mlir-translate --split-input-file -mlir-to-llvmir %s | FileCheck %s
2+
3+
module {
4+
llvm.func spir_funccc @_Z41intel_sub_group_2d_block_read_16b_8r16x1cPU3AS1viiiDv2_iPt(!llvm.ptr<1> {llvm.nonnull, llvm.readonly}, i32, i32, i32, vector<2xi32>, !llvm.ptr {llvm.nonnull, llvm.writeonly}) attributes {no_unwind, will_return}
5+
llvm.func @blockload2d_cache_control(%arg0: !llvm.ptr<1>, %arg1: i32, %arg2: i32, %arg3: i32, %arg4: i32, %arg5: i32) -> vector<8xi16> {
6+
%0 = llvm.mlir.undef : vector<2xi32>
7+
%1 = llvm.mlir.constant(0 : i32) : i32
8+
%2 = llvm.mlir.constant(1 : i32) : i32
9+
%3 = llvm.insertelement %arg4, %0[%1 : i32] : vector<2xi32>
10+
%4 = llvm.insertelement %arg5, %3[%2 : i32] : vector<2xi32>
11+
%5 = llvm.mlir.constant(8 : i32) : i32
12+
%6 = llvm.alloca %5 x i16 : (i32) -> !llvm.ptr
13+
// CHECK-LABEL: call spir_func void @_Z41intel_sub_group_2d_block_read_16b_8r16x1cPU3AS1viiiDv2_iPt
14+
// CHECK-SAME: !spirv.DecorationCacheControlINTEL ![[DECO1:.*]]
15+
llvm.call spir_funccc @_Z41intel_sub_group_2d_block_read_16b_8r16x1cPU3AS1viiiDv2_iPt(%arg0, %arg1, %arg2, %arg3, %4, %6)
16+
{function_type = !llvm.func<void (ptr<1>, i32, i32, i32, vector<2xi32>, ptr)>, linkage = #llvm.linkage<external>, no_unwind,
17+
sym_name = "_Z41intel_sub_group_2d_block_read_16b_8r16x1cPU3AS1viiiDv2_iPt", visibility_ = 0 : i64, will_return,
18+
xevm.DecorationCacheControl = [[6442 : i32, 0 : i32, 1 : i32, 0 : i32], [6442 : i32, 1 : i32, 1 : i32, 0 : i32]]}
19+
: (!llvm.ptr<1> {llvm.nonnull, llvm.readonly}, i32, i32, i32, vector<2xi32>, !llvm.ptr {llvm.nonnull, llvm.writeonly}) -> ()
20+
%7 = llvm.load %6 : !llvm.ptr -> vector<8xi16>
21+
llvm.return %7 : vector<8xi16>
22+
}
23+
}
24+
25+
// CHECK: ![[DECO1]] = !{![[DECO2:.*]], ![[DECO3:.*]]}
26+
// CHECK: ![[DECO2]] = !{i32 6442, i32 0, i32 1, i32 0}
27+
// CHECK: ![[DECO3]] = !{i32 6442, i32 1, i32 1, i32 0}
28+
29+
// -----
30+
module {
31+
llvm.func spir_funccc @_Z42intel_sub_group_2d_block_write_32b_8r16x1cPU3AS1viiiDv2_iPj(!llvm.ptr<1> {llvm.nonnull, llvm.writeonly}, i32, i32, i32, vector<2xi32>, !llvm.ptr {llvm.nonnull, llvm.readonly}) attributes {no_unwind, will_return}
32+
llvm.func @blockstore2d_cache_control(%arg0: !llvm.ptr<1>, %arg1: i32, %arg2: i32, %arg3: i32, %arg4: i32, %arg5: i32, %arg6: vector<8xi32>) {
33+
%0 = llvm.mlir.undef : vector<2xi32>
34+
%1 = llvm.mlir.constant(0 : i32) : i32
35+
%2 = llvm.mlir.constant(1 : i32) : i32
36+
%3 = llvm.insertelement %arg4, %0[%1 : i32] : vector<2xi32>
37+
%4 = llvm.insertelement %arg5, %3[%2 : i32] : vector<2xi32>
38+
%5 = llvm.mlir.constant(8 : i32) : i32
39+
%6 = llvm.alloca %5 x i32 : (i32) -> !llvm.ptr
40+
llvm.store %arg6, %6 : vector<8xi32>, !llvm.ptr
41+
// CHECK-LABEL: call spir_func void @_Z42intel_sub_group_2d_block_write_32b_8r16x1cPU3AS1viiiDv2_iPj
42+
// CHECK-SAME: !spirv.DecorationCacheControlINTEL ![[DECO1:.*]]
43+
llvm.call spir_funccc @_Z42intel_sub_group_2d_block_write_32b_8r16x1cPU3AS1viiiDv2_iPj(%arg0, %arg1, %arg2, %arg3, %4, %6)
44+
{function_type = !llvm.func<void (ptr<1>, i32, i32, i32, vector<2xi32>, ptr)>, linkage = #llvm.linkage<external>, no_unwind,
45+
sym_name = "_Z42intel_sub_group_2d_block_write_32b_8r16x1cPU3AS1viiiDv2_iPj", visibility_ = 0 : i64, will_return,
46+
xevm.DecorationCacheControl = [[6443 : i32, 0 : i32, 2 : i32, 0 : i32], [6443 : i32, 1 : i32, 2 : i32, 0 : i32]]}
47+
: (!llvm.ptr<1> {llvm.nonnull, llvm.writeonly}, i32, i32, i32, vector<2xi32>, !llvm.ptr {llvm.nonnull, llvm.readonly}) -> ()
48+
llvm.return
49+
}
50+
}
51+
52+
// CHECK: ![[DECO1]] = !{![[DECO2:.*]], ![[DECO3:.*]]}
53+
// CHECK: ![[DECO2]] = !{i32 6443, i32 0, i32 2, i32 0}
54+
// CHECK: ![[DECO3]] = !{i32 6443, i32 1, i32 2, i32 0}
55+
56+
// -----
57+
module {
58+
llvm.func spir_funccc @_Z44intel_sub_group_2d_block_prefetch_8b_8r32x1cPU3AS1viiiDv2_i(!llvm.ptr<1> {llvm.nonnull}, i32, i32, i32, vector<2xi32>) attributes {memory_effects = #llvm.memory_effects<other = none, argMem = read, inaccessibleMem = none>, no_unwind}
59+
llvm.func @blockprefetch2d(%arg0: !llvm.ptr<1>, %arg1: i32, %arg2: i32, %arg3: i32, %arg4: i32, %arg5: i32) {
60+
%0 = llvm.mlir.undef : vector<2xi32>
61+
%1 = llvm.mlir.constant(0 : i32) : i32
62+
%2 = llvm.mlir.constant(1 : i32) : i32
63+
%3 = llvm.insertelement %arg4, %0[%1 : i32] : vector<2xi32>
64+
%4 = llvm.insertelement %arg5, %3[%2 : i32] : vector<2xi32>
65+
// CHECK-LABEL: call spir_func void @_Z44intel_sub_group_2d_block_prefetch_8b_8r32x1cPU3AS1viiiDv2_i
66+
// CHECK-SAME: !spirv.DecorationCacheControlINTEL ![[DECO1:.*]]
67+
llvm.call spir_funccc @_Z44intel_sub_group_2d_block_prefetch_8b_8r32x1cPU3AS1viiiDv2_i(%arg0, %arg1, %arg2, %arg3, %4)
68+
{function_type = !llvm.func<void (ptr<1>, i32, i32, i32, vector<2xi32>)>, linkage = #llvm.linkage<external>,
69+
memory_effects = #llvm.memory_effects<other = none, argMem = read, inaccessibleMem = none>, no_unwind,
70+
sym_name = "_Z44intel_sub_group_2d_block_prefetch_8b_8r32x1cPU3AS1viiiDv2_i", visibility_ = 0 : i64,
71+
xevm.DecorationCacheControl = [[6442 : i32, 0 : i32, 1 : i32, 0 : i32], [6442 : i32, 1 : i32, 1 : i32, 0 : i32]]}
72+
: (!llvm.ptr<1> {llvm.nonnull}, i32, i32, i32, vector<2xi32>) -> ()
73+
llvm.return
74+
}
75+
}
76+
77+
// CHECK: ![[DECO1]] = !{![[DECO2:.*]], ![[DECO3:.*]]}
78+
// CHECK: ![[DECO2]] = !{i32 6442, i32 0, i32 1, i32 0}
79+
// CHECK: ![[DECO3]] = !{i32 6442, i32 1, i32 1, i32 0}
80+
81+
// -----
82+
module {
83+
llvm.func spir_funccc @_Z8prefetchPU3AS1Kcm(!llvm.ptr<1>, i64) attributes {memory_effects = #llvm.memory_effects<other = none, argMem = read, inaccessibleMem = none>, no_unwind}
84+
llvm.func @prefetch(%arg0: !llvm.ptr<1>) {
85+
%0 = llvm.mlir.constant(1 : i64) : i64
86+
// CHECK-LABEL: call spir_func void @_Z8prefetchPU3AS1Kcm
87+
// CHECK-SAME: !spirv.DecorationCacheControlINTEL ![[DECO1:.*]]
88+
llvm.call spir_funccc @_Z8prefetchPU3AS1Kcm(%arg0, %0)
89+
{function_type = !llvm.func<void (ptr<1>, i64)>, linkage = #llvm.linkage<external>,
90+
memory_effects = #llvm.memory_effects<other = none, argMem = read, inaccessibleMem = none>,
91+
no_unwind, sym_name = "_Z8prefetchPU3AS1Kcm", visibility_ = 0 : i64,
92+
xevm.DecorationCacheControl = [[6442 : i32, 0 : i32, 1 : i32, 0 : i32], [6442 : i32, 1 : i32, 1 : i32, 0 : i32]]}
93+
: (!llvm.ptr<1>, i64) -> ()
94+
llvm.return
95+
}
96+
}
97+
98+
// CHECK: ![[DECO1]] = !{![[DECO2:.*]], ![[DECO3:.*]]}
99+
// CHECK: ![[DECO2]] = !{i32 6442, i32 0, i32 1, i32 0}
100+
// CHECK: ![[DECO3]] = !{i32 6442, i32 1, i32 1, i32 0}
101+

0 commit comments

Comments
 (0)