Skip to content

[MLIR][XeVM] Add XeVM to LLVMIR translation. #150696

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

Merged
merged 2 commits into from
Jul 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions mlir/include/mlir/Target/LLVMIR/Dialect/All.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "mlir/Target/LLVMIR/Dialect/ROCDL/ROCDLToLLVMIRTranslation.h"
#include "mlir/Target/LLVMIR/Dialect/SPIRV/SPIRVToLLVMIRTranslation.h"
#include "mlir/Target/LLVMIR/Dialect/VCIX/VCIXToLLVMIRTranslation.h"
#include "mlir/Target/LLVMIR/Dialect/XeVM/XeVMToLLVMIRTranslation.h"

namespace mlir {
class DialectRegistry;
Expand All @@ -47,6 +48,7 @@ static inline void registerAllToLLVMIRTranslations(DialectRegistry &registry) {
registerROCDLDialectTranslation(registry);
registerSPIRVDialectTranslation(registry);
registerVCIXDialectTranslation(registry);
registerXeVMDialectTranslation(registry);

// Extension required for translating GPU offloading Ops.
gpu::registerOffloadingLLVMTranslationInterfaceExternalModels(registry);
Expand All @@ -63,6 +65,7 @@ registerAllGPUToLLVMIRTranslations(DialectRegistry &registry) {
registerNVVMDialectTranslation(registry);
registerROCDLDialectTranslation(registry);
registerSPIRVDialectTranslation(registry);
registerXeVMDialectTranslation(registry);

// Extension required for translating GPU offloading Ops.
gpu::registerOffloadingLLVMTranslationInterfaceExternalModels(registry);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//===-- XeVMToLLVMIRTranslation.h - XeVM to LLVM IR -------------*- C++ -*-===//
//
// This file is licensed 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 XeVM dialect to LLVM IR translation.
//
//===----------------------------------------------------------------------===//

#ifndef MLIR_TARGET_LLVMIR_DIALECT_XEVM_XEVMTOLLVMIRTRANSLATION_H
#define MLIR_TARGET_LLVMIR_DIALECT_XEVM_XEVMTOLLVMIRTRANSLATION_H

namespace mlir {

class DialectRegistry;
class MLIRContext;

/// Register the XeVM dialect and the translation from it to the LLVM IR in the
/// given registry;
void registerXeVMDialectTranslation(mlir::DialectRegistry &registry);

/// Register the XeVM dialect and the translation from it in the registry
/// associated with the given context.
void registerXeVMDialectTranslation(mlir::MLIRContext &context);

} // namespace mlir

#endif // MLIR_TARGET_LLVMIR_DIALECT_XEVM_XEVMTOLLVMIRTRANSLATION_H
1 change: 1 addition & 0 deletions mlir/lib/Target/LLVMIR/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ add_mlir_translation_library(MLIRToLLVMIRTranslationRegistration
MLIRROCDLToLLVMIRTranslation
MLIRSPIRVToLLVMIRTranslation
MLIRVCIXToLLVMIRTranslation
MLIRXeVMToLLVMIRTranslation
)

add_mlir_translation_library(MLIRTargetLLVMIRImport
Expand Down
1 change: 1 addition & 0 deletions mlir/lib/Target/LLVMIR/Dialect/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ add_subdirectory(OpenMP)
add_subdirectory(ROCDL)
add_subdirectory(SPIRV)
add_subdirectory(VCIX)
add_subdirectory(XeVM)
21 changes: 21 additions & 0 deletions mlir/lib/Target/LLVMIR/Dialect/XeVM/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
set(LLVM_OPTIONAL_SOURCES
XeVMToLLVMIRTranslation.cpp
)

add_mlir_translation_library(MLIRXeVMToLLVMIRTranslation
XeVMToLLVMIRTranslation.cpp

DEPENDS
MLIRXeVMConversionsIncGen

LINK_COMPONENTS
Core

LINK_LIBS PUBLIC
MLIRDialectUtils
MLIRIR
MLIRLLVMDialect
MLIRXeVMDialect
MLIRSupport
MLIRTargetLLVMIRExport
)
103 changes: 103 additions & 0 deletions mlir/lib/Target/LLVMIR/Dialect/XeVM/XeVMToLLVMIRTranslation.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
//===-- XeVMToLLVMIRTranslation.cpp - Translate XeVM to LLVM IR -*- C++ -*-===//
//
// This file is licensed 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 XeVM dialect and
// LLVM IR.
//
//===----------------------------------------------------------------------===//

#include "mlir/Target/LLVMIR/Dialect/XeVM/XeVMToLLVMIRTranslation.h"
#include "mlir/Dialect/LLVMIR/XeVMDialect.h"
#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/IR/Operation.h"
#include "mlir/Target/LLVMIR/ModuleTranslation.h"

#include "llvm/ADT/TypeSwitch.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Metadata.h"

#include "llvm/IR/ConstantRange.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/Support/raw_ostream.h"

using namespace mlir;
using namespace mlir::LLVM;

namespace {
/// Implementation of the dialect interface that converts operations belonging
/// to the XeVM dialect to LLVM IR.
class XeVMDialectLLVMIRTranslationInterface
: public LLVMTranslationDialectInterface {
public:
using LLVMTranslationDialectInterface::LLVMTranslationDialectInterface;

/// Attaches module-level metadata for functions marked as kernels.
LogicalResult
amendOperation(Operation *op, ArrayRef<llvm::Instruction *> instructions,
NamedAttribute attribute,
LLVM::ModuleTranslation &moduleTranslation) const final {
StringRef attrName = attribute.getName().getValue();
if (attrName == mlir::xevm::XeVMDialect::getCacheControlsAttrName()) {
auto cacheControlsArray = dyn_cast<ArrayAttr>(attribute.getValue());
if (cacheControlsArray.size() != 2) {
return op->emitOpError(
"Expected both L1 and L3 cache control attributes!");
}
if (instructions.size() != 1) {
return op->emitOpError("Expecting a single instruction");
}
return handleDecorationCacheControl(instructions.front(),
cacheControlsArray.getValue());
}
auto func = dyn_cast<LLVM::LLVMFuncOp>(op);
if (!func)
return failure();

return success();
}

private:
static LogicalResult handleDecorationCacheControl(llvm::Instruction *inst,
ArrayRef<Attribute> attrs) {
SmallVector<llvm::Metadata *> decorations;
llvm::LLVMContext &ctx = inst->getContext();
llvm::Type *i32Ty = llvm::IntegerType::getInt32Ty(ctx);
llvm::transform(
attrs, std::back_inserter(decorations),
[&ctx, i32Ty](Attribute attr) -> llvm::Metadata * {
auto valuesArray = dyn_cast<ArrayAttr>(attr).getValue();
std::array<llvm::Metadata *, 4> metadata;
llvm::transform(
valuesArray, metadata.begin(), [i32Ty](Attribute valueAttr) {
return llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
i32Ty, cast<IntegerAttr>(valueAttr).getValue()));
});
return llvm::MDNode::get(ctx, metadata);
});
constexpr llvm::StringLiteral decorationCacheControlMDName =
"spirv.DecorationCacheControlINTEL";
inst->setMetadata(decorationCacheControlMDName,
llvm::MDNode::get(ctx, decorations));
return success();
}
};
} // namespace

void mlir::registerXeVMDialectTranslation(::mlir::DialectRegistry &registry) {
registry.insert<xevm::XeVMDialect>();
registry.addExtension(+[](MLIRContext *ctx, xevm::XeVMDialect *dialect) {
dialect->addInterfaces<XeVMDialectLLVMIRTranslationInterface>();
});
}

void mlir::registerXeVMDialectTranslation(::mlir::MLIRContext &context) {
DialectRegistry registry;
registerXeVMDialectTranslation(registry);
context.appendDialectRegistry(registry);
}
21 changes: 21 additions & 0 deletions mlir/test/Target/LLVMIR/xevm.mlir
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// RUN: mlir-translate --split-input-file -mlir-to-llvmir %s | FileCheck %s

module {
llvm.func spir_funccc @_Z8prefetchPU3AS1Kcm(!llvm.ptr<1>, i64)
llvm.func @prefetch(%arg0: !llvm.ptr<1>) {
%0 = llvm.mlir.constant(1 : i64) : i64
// CHECK-LABEL: call spir_func void @_Z8prefetchPU3AS1Kcm
// CHECK-SAME: !spirv.DecorationCacheControlINTEL ![[DECO1:.*]]
llvm.call spir_funccc @_Z8prefetchPU3AS1Kcm(%arg0, %0)
{function_type = !llvm.func<void (ptr<1>, i64)>, linkage = #llvm.linkage<external>,
no_unwind, sym_name = "_Z8prefetchPU3AS1Kcm", visibility_ = 0 : i64,
xevm.DecorationCacheControl = [[6442 : i32, 0 : i32, 1 : i32, 0 : i32], [6442 : i32, 1 : i32, 1 : i32, 0 : i32]]}
: (!llvm.ptr<1>, i64) -> ()
llvm.return
}
}

// CHECK: ![[DECO1]] = !{![[DECO2:.*]], ![[DECO3:.*]]}
// CHECK: ![[DECO2]] = !{i32 6442, i32 0, i32 1, i32 0}
// CHECK: ![[DECO3]] = !{i32 6442, i32 1, i32 1, i32 0}