[Mlir-commits] [mlir] [MLIR][XeVM] Add lowering for llvm load store ops with XeVM cache control (PR #156768)
Sang Ik Lee
llvmlistbot at llvm.org
Fri Sep 5 09:25:17 PDT 2025
https://github.com/silee2 updated https://github.com/llvm/llvm-project/pull/156768
>From 669d09d0d7d685eaf67877626dac273ab0703db2 Mon Sep 17 00:00:00 2001
From: "Lee, Sang Ik" <sang.ik.lee at intel.com>
Date: Tue, 2 Sep 2025 23:47:52 +0000
Subject: [PATCH 1/6] Refactor code to make useful for LLVM load store ops.
---
mlir/lib/Conversion/XeVMToLLVM/XeVMToLLVM.cpp | 250 +++++++++++-------
1 file changed, 149 insertions(+), 101 deletions(-)
diff --git a/mlir/lib/Conversion/XeVMToLLVM/XeVMToLLVM.cpp b/mlir/lib/Conversion/XeVMToLLVM/XeVMToLLVM.cpp
index 4dfcb2b43c19c..83f3ca0d4368f 100644
--- a/mlir/lib/Conversion/XeVMToLLVM/XeVMToLLVM.cpp
+++ b/mlir/lib/Conversion/XeVMToLLVM/XeVMToLLVM.cpp
@@ -98,127 +98,175 @@ std::string mangle(StringRef baseName, ArrayRef<Type> types,
return os.str();
}
-template <bool isLoad, typename OpType>
-int32_t getL1CacheControl(OpType op) {
+static int32_t getL1CacheControl(LoadCacheControl cc) {
int32_t control = 0;
- if constexpr (isLoad) {
- switch (*op.getCacheControl()) {
- case LoadCacheControl::L1UC_L2UC_L3UC:
- case LoadCacheControl::L1UC_L2UC_L3C:
- case LoadCacheControl::L1UC_L2C_L3UC:
- case LoadCacheControl::L1UC_L2C_L3C:
- control = 1;
- break;
- case LoadCacheControl::L1C_L2UC_L3UC:
- case LoadCacheControl::L1C_L2UC_L3C:
- case LoadCacheControl::L1C_L2C_L3UC:
- case LoadCacheControl::L1C_L2C_L3C:
- control = 2;
- break;
- case LoadCacheControl::L1S_L2UC_L3UC:
- case LoadCacheControl::L1S_L2UC_L3C:
- case LoadCacheControl::L1S_L2C_L3UC:
- case LoadCacheControl::L1S_L2C_L3C:
- control = 3;
- break;
- case LoadCacheControl::INVALIDATE_READ:
- control = 4;
- break;
- }
- } else {
- switch (*op.getCacheControl()) {
- case StoreCacheControl::L1UC_L2UC_L3UC:
- case StoreCacheControl::L1UC_L2UC_L3WB:
- case StoreCacheControl::L1UC_L2WB_L3UC:
- case StoreCacheControl::L1UC_L2WB_L3WB:
- control = 1;
- break;
- case StoreCacheControl::L1WT_L2UC_L3UC:
- case StoreCacheControl::L1WT_L2UC_L3WB:
- case StoreCacheControl::L1WT_L2WB_L3UC:
- case StoreCacheControl::L1WT_L2WB_L3WB:
- control = 2;
- break;
- case StoreCacheControl::L1S_L2UC_L3UC:
- case StoreCacheControl::L1S_L2UC_L3WB:
- case StoreCacheControl::L1S_L2WB_L3UC:
- case StoreCacheControl::L1S_L2WB_L3WB:
- control = 3;
- break;
- case StoreCacheControl::L1WB_L2UC_L3UC:
- case StoreCacheControl::L1WB_L2WB_L3UC:
- case StoreCacheControl::L1WB_L2UC_L3WB:
- control = 4;
- break;
- }
+ switch (cc) {
+ case LoadCacheControl::L1UC_L2UC_L3UC:
+ case LoadCacheControl::L1UC_L2UC_L3C:
+ case LoadCacheControl::L1UC_L2C_L3UC:
+ case LoadCacheControl::L1UC_L2C_L3C:
+ control = 1;
+ break;
+ case LoadCacheControl::L1C_L2UC_L3UC:
+ case LoadCacheControl::L1C_L2UC_L3C:
+ case LoadCacheControl::L1C_L2C_L3UC:
+ case LoadCacheControl::L1C_L2C_L3C:
+ control = 2;
+ break;
+ case LoadCacheControl::L1S_L2UC_L3UC:
+ case LoadCacheControl::L1S_L2UC_L3C:
+ case LoadCacheControl::L1S_L2C_L3UC:
+ case LoadCacheControl::L1S_L2C_L3C:
+ control = 3;
+ break;
+ case LoadCacheControl::INVALIDATE_READ:
+ control = 4;
+ break;
}
return control;
}
-template <bool isLoad, typename OpType>
-int32_t getL3CacheControl(OpType op) {
+static int32_t getL1CacheControl(StoreCacheControl cc) {
int32_t control = 0;
- if constexpr (isLoad) {
- switch (*op.getCacheControl()) {
- case LoadCacheControl::L1UC_L2UC_L3UC:
- case LoadCacheControl::L1UC_L2C_L3UC:
- case LoadCacheControl::L1C_L2UC_L3UC:
- case LoadCacheControl::L1C_L2C_L3UC:
- case LoadCacheControl::L1S_L2UC_L3UC:
- case LoadCacheControl::L1S_L2C_L3UC:
- control = 1;
- break;
- case LoadCacheControl::L1UC_L2UC_L3C:
- case LoadCacheControl::L1UC_L2C_L3C:
- case LoadCacheControl::L1C_L2UC_L3C:
- case LoadCacheControl::L1C_L2C_L3C:
- case LoadCacheControl::L1S_L2UC_L3C:
- case LoadCacheControl::L1S_L2C_L3C:
- control = 2;
- break;
- case LoadCacheControl::INVALIDATE_READ:
- control = 4;
- break;
- }
- } else {
- switch (*op.getCacheControl()) {
- case StoreCacheControl::L1UC_L2UC_L3UC:
- case StoreCacheControl::L1UC_L2WB_L3UC:
- case StoreCacheControl::L1WT_L2UC_L3UC:
- case StoreCacheControl::L1WT_L2WB_L3UC:
- case StoreCacheControl::L1S_L2UC_L3UC:
- case StoreCacheControl::L1S_L2WB_L3UC:
- case StoreCacheControl::L1WB_L2UC_L3UC:
- case StoreCacheControl::L1WB_L2WB_L3UC:
- control = 1;
- break;
- case StoreCacheControl::L1UC_L2UC_L3WB:
- case StoreCacheControl::L1UC_L2WB_L3WB:
- case StoreCacheControl::L1WT_L2UC_L3WB:
- case StoreCacheControl::L1WT_L2WB_L3WB:
- case StoreCacheControl::L1S_L2UC_L3WB:
- case StoreCacheControl::L1S_L2WB_L3WB:
- case StoreCacheControl::L1WB_L2UC_L3WB:
- control = 2;
- break;
- }
+ switch (cc) {
+ case StoreCacheControl::L1UC_L2UC_L3UC:
+ case StoreCacheControl::L1UC_L2UC_L3WB:
+ case StoreCacheControl::L1UC_L2WB_L3UC:
+ case StoreCacheControl::L1UC_L2WB_L3WB:
+ control = 1;
+ break;
+ case StoreCacheControl::L1WT_L2UC_L3UC:
+ case StoreCacheControl::L1WT_L2UC_L3WB:
+ case StoreCacheControl::L1WT_L2WB_L3UC:
+ case StoreCacheControl::L1WT_L2WB_L3WB:
+ control = 2;
+ break;
+ case StoreCacheControl::L1S_L2UC_L3UC:
+ case StoreCacheControl::L1S_L2UC_L3WB:
+ case StoreCacheControl::L1S_L2WB_L3UC:
+ case StoreCacheControl::L1S_L2WB_L3WB:
+ control = 3;
+ break;
+ case StoreCacheControl::L1WB_L2UC_L3UC:
+ case StoreCacheControl::L1WB_L2WB_L3UC:
+ case StoreCacheControl::L1WB_L2UC_L3WB:
+ control = 4;
+ break;
}
return control;
}
+static int32_t getL3CacheControl(LoadCacheControl cc) {
+ int32_t control = 0;
+ switch (cc) {
+ case LoadCacheControl::L1UC_L2UC_L3UC:
+ case LoadCacheControl::L1UC_L2C_L3UC:
+ case LoadCacheControl::L1C_L2UC_L3UC:
+ case LoadCacheControl::L1C_L2C_L3UC:
+ case LoadCacheControl::L1S_L2UC_L3UC:
+ case LoadCacheControl::L1S_L2C_L3UC:
+ control = 1;
+ break;
+ case LoadCacheControl::L1UC_L2UC_L3C:
+ case LoadCacheControl::L1UC_L2C_L3C:
+ case LoadCacheControl::L1C_L2UC_L3C:
+ case LoadCacheControl::L1C_L2C_L3C:
+ case LoadCacheControl::L1S_L2UC_L3C:
+ case LoadCacheControl::L1S_L2C_L3C:
+ control = 2;
+ break;
+ case LoadCacheControl::INVALIDATE_READ:
+ control = 4;
+ break;
+ }
+ return control;
+}
+
+static int32_t getL3CacheControl(StoreCacheControl cc) {
+ int32_t control = 0;
+ switch (cc) {
+ case StoreCacheControl::L1UC_L2UC_L3UC:
+ case StoreCacheControl::L1UC_L2WB_L3UC:
+ case StoreCacheControl::L1WT_L2UC_L3UC:
+ case StoreCacheControl::L1WT_L2WB_L3UC:
+ case StoreCacheControl::L1S_L2UC_L3UC:
+ case StoreCacheControl::L1S_L2WB_L3UC:
+ case StoreCacheControl::L1WB_L2UC_L3UC:
+ case StoreCacheControl::L1WB_L2WB_L3UC:
+ control = 1;
+ break;
+ case StoreCacheControl::L1UC_L2UC_L3WB:
+ case StoreCacheControl::L1UC_L2WB_L3WB:
+ case StoreCacheControl::L1WT_L2UC_L3WB:
+ case StoreCacheControl::L1WT_L2WB_L3WB:
+ case StoreCacheControl::L1S_L2UC_L3WB:
+ case StoreCacheControl::L1S_L2WB_L3WB:
+ case StoreCacheControl::L1WB_L2UC_L3WB:
+ control = 2;
+ break;
+ }
+ return control;
+}
+
+static std::optional<LoadCacheControl> getCacheControl(PrefetchOp op) {
+ return op.getCacheControl();
+}
+
+static std::optional<LoadCacheControl> getCacheControl(BlockLoad2dOp op) {
+ return op.getCacheControl();
+}
+
+static std::optional<LoadCacheControl> getCacheControl(BlockPrefetch2dOp op) {
+ return op.getCacheControl();
+}
+
+static std::optional<StoreCacheControl> getCacheControl(BlockStore2dOp op) {
+ return op.getCacheControl();
+}
+
+static std::optional<LoadCacheControl> getCacheControl(LLVM::LoadOp op) {
+ if (op->hasAttr("cache_control")) {
+ auto attr = op->getAttrOfType<xevm::LoadCacheControlAttr>("cache_control");
+ if (!attr)
+ return std::nullopt;
+ return std::optional<LoadCacheControl>(attr.getValue());
+ }
+ return std::nullopt;
+}
+
+static std::optional<StoreCacheControl> getCacheControl(LLVM::StoreOp op) {
+ if (op->hasAttr("cache_control")) {
+ auto attr = op->getAttrOfType<xevm::StoreCacheControlAttr>("cache_control");
+ if (!attr)
+ return std::nullopt;
+ return std::optional<StoreCacheControl>(attr.getValue());
+ }
+ return std::nullopt;
+}
+
+template <typename OpType>
+int32_t getL1CacheControl(OpType op) {
+ return getL1CacheControl(*getCacheControl(op));
+}
+
+template <typename OpType>
+int32_t getL3CacheControl(OpType op) {
+ return getL3CacheControl(*getCacheControl(op));
+}
+
template <bool isLoad, typename OpType>
static std::optional<ArrayAttr>
getCacheControlMetadata(ConversionPatternRewriter &rewriter, OpType op) {
- if (!op.getCacheControl())
+ if (!getCacheControl(op))
return {};
constexpr int32_t decorationCacheControlArity{4};
constexpr int32_t loadCacheControlKey{6442};
constexpr int32_t storeCacheControlKey{6443};
const int32_t controlKey{isLoad ? loadCacheControlKey : storeCacheControlKey};
SmallVector<int32_t, decorationCacheControlArity> decorationsL1{
- controlKey, 0, getL1CacheControl<isLoad, OpType>(op), 0};
+ controlKey, 0, getL1CacheControl<OpType>(op), 0};
SmallVector<int32_t, decorationCacheControlArity> decorationsL3{
- controlKey, 1, getL3CacheControl<isLoad, OpType>(op), 0};
+ controlKey, 1, getL3CacheControl<OpType>(op), 0};
auto arrayAttrL1 = rewriter.getI32ArrayAttr(decorationsL1);
auto arrayAttrL3 = rewriter.getI32ArrayAttr(decorationsL3);
>From 733d437ddd2a6021b6ee202f0d0e3dcc310ff38f Mon Sep 17 00:00:00 2001
From: "Lee, Sang Ik" <sang.ik.lee at intel.com>
Date: Tue, 2 Sep 2025 23:57:40 +0000
Subject: [PATCH 2/6] Mark LLVM load and store op with cache_control attr as
illegal.
---
mlir/lib/Conversion/XeVMToLLVM/XeVMToLLVM.cpp | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/mlir/lib/Conversion/XeVMToLLVM/XeVMToLLVM.cpp b/mlir/lib/Conversion/XeVMToLLVM/XeVMToLLVM.cpp
index 83f3ca0d4368f..154f333f221b7 100644
--- a/mlir/lib/Conversion/XeVMToLLVM/XeVMToLLVM.cpp
+++ b/mlir/lib/Conversion/XeVMToLLVM/XeVMToLLVM.cpp
@@ -632,6 +632,10 @@ struct ConvertXeVMToLLVMPass
void runOnOperation() override {
ConversionTarget target(getContext());
target.addLegalDialect<LLVM::LLVMDialect>();
+ target.addDynamicallyLegalOp<LLVM::LoadOp>(
+ [](LLVM::LoadOp op) { return !op->hasAttr("cache_control"); });
+ target.addDynamicallyLegalOp<LLVM::StoreOp>(
+ [](LLVM::StoreOp op) { return !op->hasAttr("cache_control"); });
target.addIllegalDialect<XeVMDialect>();
RewritePatternSet patterns(&getContext());
populateXeVMToLLVMConversionPatterns(patterns);
>From 8ae4428f4f39e8829d3fa41b636d09b4ac2cc81c Mon Sep 17 00:00:00 2001
From: "Lee, Sang Ik" <sang.ik.lee at intel.com>
Date: Wed, 3 Sep 2025 16:37:09 +0000
Subject: [PATCH 3/6] convert xevm to llvm : handle LLVM load / store with
cache_control.
---
mlir/lib/Conversion/XeVMToLLVM/XeVMToLLVM.cpp | 22 +++++++++++++++++--
1 file changed, 20 insertions(+), 2 deletions(-)
diff --git a/mlir/lib/Conversion/XeVMToLLVM/XeVMToLLVM.cpp b/mlir/lib/Conversion/XeVMToLLVM/XeVMToLLVM.cpp
index 154f333f221b7..f4db274b70123 100644
--- a/mlir/lib/Conversion/XeVMToLLVM/XeVMToLLVM.cpp
+++ b/mlir/lib/Conversion/XeVMToLLVM/XeVMToLLVM.cpp
@@ -616,6 +616,23 @@ class LoadStorePrefetchToOCLPattern : public OpConversionPattern<OpType> {
return success();
}
};
+template <typename OpType>
+class LLVMLoadStoreToOCLPattern : public OpConversionPattern<OpType> {
+ using OpConversionPattern<OpType>::OpConversionPattern;
+ LogicalResult
+ matchAndRewrite(OpType op, typename OpType::Adaptor adaptor,
+ ConversionPatternRewriter &rewriter) const override {
+ if (!op->hasAttr("cache_control"))
+ return failure();
+ constexpr bool isLoad = std::is_same_v<OpType, LLVM::LoadOp>;
+ auto loc = op.getLoc();
+ std::optional<ArrayAttr> optCacheControls =
+ getCacheControlMetadata<isLoad>(rewriter, op);
+ op->setAttr(XeVMDialect::getCacheControlsAttrName(), *optCacheControls);
+ op->removeAttr("cache_control");
+ return success();
+ }
+};
//===----------------------------------------------------------------------===//
// Pass Definition
@@ -676,8 +693,9 @@ void ::mlir::populateXeVMToLLVMConversionPatterns(RewritePatternSet &patterns) {
patterns.add<LoadStorePrefetchToOCLPattern<BlockLoad2dOp>,
LoadStorePrefetchToOCLPattern<BlockStore2dOp>,
LoadStorePrefetchToOCLPattern<BlockPrefetch2dOp>,
- MMAToOCLPattern, MemfenceToOCLPattern, PrefetchToOCLPattern>(
- patterns.getContext());
+ MMAToOCLPattern, MemfenceToOCLPattern, PrefetchToOCLPattern,
+ LLVMLoadStoreToOCLPattern<LLVM::LoadOp>,
+ LLVMLoadStoreToOCLPattern<LLVM::StoreOp>>(patterns.getContext());
}
void ::mlir::registerConvertXeVMToLLVMInterface(DialectRegistry ®istry) {
>From 695e1413e8e5e58188609754f2db5e14c834d24a Mon Sep 17 00:00:00 2001
From: "Lee, Sang Ik" <sang.ik.lee at intel.com>
Date: Wed, 3 Sep 2025 20:43:41 +0000
Subject: [PATCH 4/6] Fix convert to llvm issues.
---
.../mlir/Conversion/XeVMToLLVM/XeVMToLLVM.h | 4 +++-
mlir/lib/Conversion/XeVMToLLVM/XeVMToLLVM.cpp | 17 +++++++----------
.../Conversion/XeVMToLLVM/xevm-to-llvm.mlir | 19 +++++++++++++++++++
3 files changed, 29 insertions(+), 11 deletions(-)
diff --git a/mlir/include/mlir/Conversion/XeVMToLLVM/XeVMToLLVM.h b/mlir/include/mlir/Conversion/XeVMToLLVM/XeVMToLLVM.h
index 7ffdbd4307f9e..f591407b602df 100644
--- a/mlir/include/mlir/Conversion/XeVMToLLVM/XeVMToLLVM.h
+++ b/mlir/include/mlir/Conversion/XeVMToLLVM/XeVMToLLVM.h
@@ -11,6 +11,7 @@
#include <memory>
namespace mlir {
+class ConversionTarget;
class DialectRegistry;
class LLVMTypeConverter;
class RewritePatternSet;
@@ -19,7 +20,8 @@ class Pass;
#define GEN_PASS_DECL_CONVERTXEVMTOLLVMPASS
#include "mlir/Conversion/Passes.h.inc"
-void populateXeVMToLLVMConversionPatterns(RewritePatternSet &patterns);
+void populateXeVMToLLVMConversionPatterns(ConversionTarget &target,
+ RewritePatternSet &patterns);
void registerConvertXeVMToLLVMInterface(DialectRegistry ®istry);
} // namespace mlir
diff --git a/mlir/lib/Conversion/XeVMToLLVM/XeVMToLLVM.cpp b/mlir/lib/Conversion/XeVMToLLVM/XeVMToLLVM.cpp
index f4db274b70123..41f5d6d908c6c 100644
--- a/mlir/lib/Conversion/XeVMToLLVM/XeVMToLLVM.cpp
+++ b/mlir/lib/Conversion/XeVMToLLVM/XeVMToLLVM.cpp
@@ -625,7 +625,6 @@ class LLVMLoadStoreToOCLPattern : public OpConversionPattern<OpType> {
if (!op->hasAttr("cache_control"))
return failure();
constexpr bool isLoad = std::is_same_v<OpType, LLVM::LoadOp>;
- auto loc = op.getLoc();
std::optional<ArrayAttr> optCacheControls =
getCacheControlMetadata<isLoad>(rewriter, op);
op->setAttr(XeVMDialect::getCacheControlsAttrName(), *optCacheControls);
@@ -648,14 +647,8 @@ struct ConvertXeVMToLLVMPass
void runOnOperation() override {
ConversionTarget target(getContext());
- target.addLegalDialect<LLVM::LLVMDialect>();
- target.addDynamicallyLegalOp<LLVM::LoadOp>(
- [](LLVM::LoadOp op) { return !op->hasAttr("cache_control"); });
- target.addDynamicallyLegalOp<LLVM::StoreOp>(
- [](LLVM::StoreOp op) { return !op->hasAttr("cache_control"); });
- target.addIllegalDialect<XeVMDialect>();
RewritePatternSet patterns(&getContext());
- populateXeVMToLLVMConversionPatterns(patterns);
+ populateXeVMToLLVMConversionPatterns(target, patterns);
if (failed(applyPartialConversion(getOperation(), target,
std::move(patterns))))
signalPassFailure();
@@ -680,7 +673,7 @@ struct XeVMToLLVMDialectInterface : public ConvertToLLVMPatternInterface {
void populateConvertToLLVMConversionPatterns(
ConversionTarget &target, LLVMTypeConverter &typeConverter,
RewritePatternSet &patterns) const final {
- populateXeVMToLLVMConversionPatterns(patterns);
+ populateXeVMToLLVMConversionPatterns(target, patterns);
}
};
} // namespace
@@ -689,7 +682,11 @@ struct XeVMToLLVMDialectInterface : public ConvertToLLVMPatternInterface {
// Pattern Population
//===----------------------------------------------------------------------===//
-void ::mlir::populateXeVMToLLVMConversionPatterns(RewritePatternSet &patterns) {
+void ::mlir::populateXeVMToLLVMConversionPatterns(ConversionTarget &target,
+ RewritePatternSet &patterns) {
+ target.addDynamicallyLegalDialect<LLVM::LLVMDialect>(
+ [](Operation *op) { return !op->hasAttr("cache_control"); });
+ target.addIllegalDialect<XeVMDialect>();
patterns.add<LoadStorePrefetchToOCLPattern<BlockLoad2dOp>,
LoadStorePrefetchToOCLPattern<BlockStore2dOp>,
LoadStorePrefetchToOCLPattern<BlockPrefetch2dOp>,
diff --git a/mlir/test/Conversion/XeVMToLLVM/xevm-to-llvm.mlir b/mlir/test/Conversion/XeVMToLLVM/xevm-to-llvm.mlir
index bdbb12bbe0cbb..8f60a0797652b 100644
--- a/mlir/test/Conversion/XeVMToLLVM/xevm-to-llvm.mlir
+++ b/mlir/test/Conversion/XeVMToLLVM/xevm-to-llvm.mlir
@@ -242,3 +242,22 @@ llvm.func @prefetch(%ptr: !llvm.ptr<1>) {
llvm.return
}
+// -----
+// CHECK-LABEL: llvm.func @llvm.load
+llvm.func @llvm.load(%a: !llvm.ptr<1>) -> i32 {
+ // CHECK: xevm.DecorationCacheControl =
+ // CHECK-SAME: 6442 : i32, 0 : i32, 1 : i32, 0 : i32
+ // CHECK-SAME: 6442 : i32, 1 : i32, 1 : i32, 0 : i32
+ %val = llvm.load %a {cache_control=#xevm.load_cache_control<L1uc_L2uc_L3uc>} : !llvm.ptr<1> -> i32
+ llvm.return %val : i32
+}
+
+// -----
+// CHECK-LABEL: llvm.func @llvm.store
+llvm.func @llvm.store(%a: !llvm.ptr<1>, %val: i32) {
+ // CHECK: xevm.DecorationCacheControl =
+ // CHECK-SAME: 6443 : i32, 0 : i32, 2 : i32, 0 : i32
+ // CHECK-SAME: 6443 : i32, 1 : i32, 2 : i32, 0 : i32
+ llvm.store %val, %a {cache_control=#xevm.store_cache_control<L1wt_L2uc_L3wb>} : i32, !llvm.ptr<1>
+ llvm.return
+}
>From ab9840b18e1014673346fa140c255027a2582c0a Mon Sep 17 00:00:00 2001
From: "Lee, Sang Ik" <sang.ik.lee at intel.com>
Date: Wed, 3 Sep 2025 21:33:05 +0000
Subject: [PATCH 5/6] Handle amending llvm load/store cache control and add
tests.
---
.../Dialect/XeVM/XeVMToLLVMIRTranslation.cpp | 4 ---
mlir/test/Target/LLVMIR/xevm.mlir | 32 +++++++++++++++++++
2 files changed, 32 insertions(+), 4 deletions(-)
diff --git a/mlir/lib/Target/LLVMIR/Dialect/XeVM/XeVMToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/XeVM/XeVMToLLVMIRTranslation.cpp
index 73b166d045d5b..7e9318ad3c019 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/XeVM/XeVMToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/XeVM/XeVMToLLVMIRTranslation.cpp
@@ -55,10 +55,6 @@ class XeVMDialectLLVMIRTranslationInterface
return handleDecorationCacheControl(instructions.front(),
cacheControlsArray.getValue());
}
- auto func = dyn_cast<LLVM::LLVMFuncOp>(op);
- if (!func)
- return failure();
-
return success();
}
diff --git a/mlir/test/Target/LLVMIR/xevm.mlir b/mlir/test/Target/LLVMIR/xevm.mlir
index a3dd0b6c17914..112d923607060 100644
--- a/mlir/test/Target/LLVMIR/xevm.mlir
+++ b/mlir/test/Target/LLVMIR/xevm.mlir
@@ -19,3 +19,35 @@ module {
// CHECK: ![[DECO2]] = !{i32 6442, i32 0, i32 1, i32 0}
// CHECK: ![[DECO3]] = !{i32 6442, i32 1, i32 1, i32 0}
+// -----
+module {
+ // CHECK-LABEL: define i32 @load(ptr addrspace(1)
+ // CHECK-SAME: %[[ARG0:.*]]) {
+ llvm.func @load(%arg0: !llvm.ptr<1>) -> i32 {
+ // CHECK: load i32, ptr addrspace(1) %[[ARG0]], align 4,
+ // CHECK-SAME: !spirv.DecorationCacheControlINTEL ![[DECO1:.*]]
+ %0 = llvm.load %arg0 {xevm.DecorationCacheControl = [[6442 : i32, 0 : i32, 1 : i32, 0 : i32], [6442 : i32, 1 : i32, 1 : i32, 0 : i32]]} : !llvm.ptr<1> -> i32
+ llvm.return %0 : i32
+ }
+}
+
+// CHECK: ![[DECO1]] = !{![[DECO2:.*]], ![[DECO3:.*]]}
+// CHECK: ![[DECO2]] = !{i32 6442, i32 0, i32 1, i32 0}
+// CHECK: ![[DECO3]] = !{i32 6442, i32 1, i32 1, i32 0}
+
+// -----
+module {
+ // CHECK-LABEL: define void @store(ptr addrspace(1)
+ // CHECK-SAME: %[[ARG0:.*]], i32 %[[ARG1:.*]]) {
+ llvm.func @store(%arg0: !llvm.ptr<1>, %arg1: i32) {
+ // CHECK: store i32 %[[ARG1]], ptr addrspace(1) %[[ARG0]], align 4,
+ // CHECK-SAME: !spirv.DecorationCacheControlINTEL ![[DECO1:.*]]
+ llvm.store %arg1, %arg0 {xevm.DecorationCacheControl = [[6443 : i32, 0 : i32, 2 : i32, 0 : i32], [6443 : i32, 1 : i32, 2 : i32, 0 : i32]]} : i32, !llvm.ptr<1>
+ llvm.return
+ }
+}
+
+// CHECK: ![[DECO1]] = !{![[DECO2:.*]], ![[DECO3:.*]]}
+// CHECK: ![[DECO2]] = !{i32 6443, i32 0, i32 2, i32 0}
+// CHECK: ![[DECO3]] = !{i32 6443, i32 1, i32 2, i32 0}
+
>From 3ed1f6b5f70d0ce280588a1520adcc048d4b8e35 Mon Sep 17 00:00:00 2001
From: "Lee, Sang Ik" <sang.ik.lee at intel.com>
Date: Fri, 5 Sep 2025 16:24:25 +0000
Subject: [PATCH 6/6] Remove template arg.
---
mlir/lib/Conversion/XeVMToLLVM/XeVMToLLVM.cpp | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/mlir/lib/Conversion/XeVMToLLVM/XeVMToLLVM.cpp b/mlir/lib/Conversion/XeVMToLLVM/XeVMToLLVM.cpp
index 41f5d6d908c6c..0f90acf0d9c39 100644
--- a/mlir/lib/Conversion/XeVMToLLVM/XeVMToLLVM.cpp
+++ b/mlir/lib/Conversion/XeVMToLLVM/XeVMToLLVM.cpp
@@ -254,7 +254,7 @@ int32_t getL3CacheControl(OpType op) {
return getL3CacheControl(*getCacheControl(op));
}
-template <bool isLoad, typename OpType>
+template <typename OpType>
static std::optional<ArrayAttr>
getCacheControlMetadata(ConversionPatternRewriter &rewriter, OpType op) {
if (!getCacheControl(op))
@@ -262,6 +262,10 @@ getCacheControlMetadata(ConversionPatternRewriter &rewriter, OpType op) {
constexpr int32_t decorationCacheControlArity{4};
constexpr int32_t loadCacheControlKey{6442};
constexpr int32_t storeCacheControlKey{6443};
+ constexpr bool isLoad = std::is_same_v<OpType, BlockLoad2dOp> ||
+ std::is_same_v<OpType, BlockPrefetch2dOp> ||
+ std::is_same_v<OpType, LLVM::LoadOp> ||
+ std::is_same_v<OpType, PrefetchOp>;
const int32_t controlKey{isLoad ? loadCacheControlKey : storeCacheControlKey};
SmallVector<int32_t, decorationCacheControlArity> decorationsL1{
controlKey, 0, getL1CacheControl<OpType>(op), 0};
@@ -446,7 +450,7 @@ class PrefetchToOCLPattern : public OpConversionPattern<PrefetchOp> {
rewriter, fnName, LLVM::LLVMVoidType::get(rewriter.getContext()),
argTypes, args, {}, funcAttr, op.getOperation());
if (std::optional<ArrayAttr> optCacheControls =
- getCacheControlMetadata<true>(rewriter, op))
+ getCacheControlMetadata(rewriter, op))
call->setAttr(XeVMDialect::getCacheControlsAttrName(), *optCacheControls);
rewriter.eraseOp(op);
return success();
@@ -605,7 +609,7 @@ class LoadStorePrefetchToOCLPattern : public OpConversionPattern<OpType> {
rewriter, funcName, LLVM::LLVMVoidType::get(rewriter.getContext()),
argTypes, args, paramAttrs, funcAttr, op.getOperation());
if (std::optional<ArrayAttr> optCacheControls =
- getCacheControlMetadata < isLoad || isPrefetch > (rewriter, op)) {
+ getCacheControlMetadata(rewriter, op)) {
call->setAttr(XeVMDialect::getCacheControlsAttrName(), *optCacheControls);
}
if constexpr (isLoad)
@@ -624,9 +628,8 @@ class LLVMLoadStoreToOCLPattern : public OpConversionPattern<OpType> {
ConversionPatternRewriter &rewriter) const override {
if (!op->hasAttr("cache_control"))
return failure();
- constexpr bool isLoad = std::is_same_v<OpType, LLVM::LoadOp>;
std::optional<ArrayAttr> optCacheControls =
- getCacheControlMetadata<isLoad>(rewriter, op);
+ getCacheControlMetadata(rewriter, op);
op->setAttr(XeVMDialect::getCacheControlsAttrName(), *optCacheControls);
op->removeAttr("cache_control");
return success();
More information about the Mlir-commits
mailing list