[Mlir-commits] [mlir] [MLIR][XeVM] Rewrite llvm.alloca if addr_space is not 0 (PR #183417)

Sang Ik Lee llvmlistbot at llvm.org
Wed Feb 25 15:55:12 PST 2026


https://github.com/silee2 updated https://github.com/llvm/llvm-project/pull/183417

>From 00fea1b61937cb5f5d4bc27c0b82a5c2df00dd33 Mon Sep 17 00:00:00 2001
From: "Lee, Sang Ik" <sang.ik.lee at intel.com>
Date: Wed, 25 Feb 2026 23:16:28 +0000
Subject: [PATCH 1/2] [MLIR][XeVM] Rewrite llvm.alloca if addr_space is not 0

---
 mlir/lib/Conversion/XeVMToLLVM/XeVMToLLVM.cpp | 60 ++++++++++++++++++-
 .../Conversion/XeVMToLLVM/rewrite_alloca.mlir | 27 +++++++++
 2 files changed, 84 insertions(+), 3 deletions(-)
 create mode 100644 mlir/test/Conversion/XeVMToLLVM/rewrite_alloca.mlir

diff --git a/mlir/lib/Conversion/XeVMToLLVM/XeVMToLLVM.cpp b/mlir/lib/Conversion/XeVMToLLVM/XeVMToLLVM.cpp
index e7537ba1f0a79..cfbb58581625b 100644
--- a/mlir/lib/Conversion/XeVMToLLVM/XeVMToLLVM.cpp
+++ b/mlir/lib/Conversion/XeVMToLLVM/XeVMToLLVM.cpp
@@ -14,9 +14,11 @@
 #include "mlir/Dialect/LLVMIR/XeVMDialect.h"
 #include "mlir/Pass/Pass.h"
 #include "mlir/Support/LLVM.h"
+#include "llvm/ADT/ArrayRef.h"
 #include "llvm/Support/FormatVariadic.h"
 
 #include "mlir/IR/BuiltinTypes.h"
+#include "mlir/IR/Matchers.h"
 #include "mlir/IR/Types.h"
 #include "mlir/Transforms/GreedyPatternRewriteDriver.h"
 
@@ -836,6 +838,46 @@ class SubgroupOpWorkitemOpToOCLPattern : public OpConversionPattern<OpType> {
   }
 };
 
+static unsigned getNextGlobalIdx() {
+  static unsigned globalIdx = 0;
+  return globalIdx++;
+}
+
+class AllocaToGlobalPattern : public OpConversionPattern<LLVM::AllocaOp> {
+  using OpConversionPattern::OpConversionPattern;
+  LogicalResult
+  matchAndRewrite(LLVM::AllocaOp op, LLVM::AllocaOp::Adaptor adaptor,
+                  ConversionPatternRewriter &rewriter) const override {
+    auto moduleOp = op->getParentOfType<ModuleOp>();
+    if (!moduleOp)
+      return failure();
+    auto ptrType = cast<LLVM::LLVMPointerType>(op.getType());
+    auto addrSpace = ptrType.getAddressSpace();
+    if (addrSpace != 3)
+      return failure();
+    auto alignment = op.getAlignment();
+    auto val = op.getArraySize();
+    APInt cst;
+    if (!matchPattern(val, m_ConstantInt(&cst)))
+      return failure();
+    auto loc = op.getLoc();
+    auto globalType = LLVM::LLVMArrayType::get(
+        rewriter.getContext(), op.getElemType(), cst.getZExtValue());
+    auto saveIP = rewriter.saveInsertionPoint();
+    rewriter.setInsertionPointToStart(moduleOp.getBody());
+    auto globalVar = LLVM::GlobalOp::create(
+        rewriter, loc, globalType, /*isConstant=*/false,
+        /*linkage=*/LLVM::Linkage::Internal,
+        /*name=*/std::string("__global_alloca_") +
+            std::to_string(getNextGlobalIdx()),
+        /*value=*/Attribute(),
+        /*alignment=*/alignment ? *alignment : 0, /*addrSpace=*/addrSpace);
+    rewriter.restoreInsertionPoint(saveIP);
+    rewriter.replaceOpWithNewOp<LLVM::AddressOfOp>(op, globalVar);
+    return success();
+  }
+};
+
 static bool isExtractingContiguousSlice(LLVM::ShuffleVectorOp op) {
   if (op.getV1() != op.getV2())
     return false;
@@ -1014,8 +1056,19 @@ struct ConvertXeVMToLLVMPass
 
 void ::mlir::populateXeVMToLLVMConversionPatterns(ConversionTarget &target,
                                                   RewritePatternSet &patterns) {
-  target.addDynamicallyLegalDialect<LLVM::LLVMDialect>(
-      [](Operation *op) { return !op->hasAttr("cache_control"); });
+  // some LLVM operations need to be converted.
+  target.addDynamicallyLegalDialect<LLVM::LLVMDialect>([](Operation *op) {
+    // addrspace 0 (function) is the default for alloca, and it is legal.
+    // other address spaces need to replaced with llvm global.
+    if (isa<LLVM::AllocaOp>(op)) {
+      LLVM::AllocaOp aOp = cast<LLVM::AllocaOp>(op);
+      LLVM::LLVMPointerType pTy = cast<LLVM::LLVMPointerType>(aOp.getType());
+      auto addrSpace = pTy.getAddressSpace();
+      return addrSpace == 0;
+    }
+    // cache_control attribute should be converted.
+    return !op->hasAttr("cache_control");
+  });
   target.addIllegalDialect<XeVMDialect>();
   patterns.add<LoadStorePrefetchToOCLPattern<BlockLoad2dOp>,
                LoadStorePrefetchToOCLPattern<BlockStore2dOp>,
@@ -1039,6 +1092,7 @@ void ::mlir::populateXeVMToLLVMConversionPatterns(ConversionTarget &target,
                LaunchConfigOpToOCLPattern<GridDimZOp>,
                SubgroupOpWorkitemOpToOCLPattern<LaneIdOp>,
                SubgroupOpWorkitemOpToOCLPattern<SubgroupIdOp>,
-               SubgroupOpWorkitemOpToOCLPattern<SubgroupSizeOp>>(
+               SubgroupOpWorkitemOpToOCLPattern<SubgroupSizeOp>,
+               AllocaToGlobalPattern>(
       patterns.getContext());
 }
diff --git a/mlir/test/Conversion/XeVMToLLVM/rewrite_alloca.mlir b/mlir/test/Conversion/XeVMToLLVM/rewrite_alloca.mlir
new file mode 100644
index 0000000000000..5db8e05eda4a6
--- /dev/null
+++ b/mlir/test/Conversion/XeVMToLLVM/rewrite_alloca.mlir
@@ -0,0 +1,27 @@
+// RUN: mlir-opt --convert-xevm-to-llvm --split-input-file %s | FileCheck %s
+
+module {
+  // CHECK: llvm.mlir.global internal @__global_alloca_2() {addr_space = 3 : i32, alignment = 8 : i64} : !llvm.array<10 x i32>
+  // CHECK: llvm.mlir.global internal @__global_alloca_1() {addr_space = 3 : i32, alignment = 8 : i64} : !llvm.array<10 x i32>
+  // CHECK: llvm.mlir.global internal @__global_alloca_0() {addr_space = 3 : i32, alignment = 8 : i64} : !llvm.array<10 x i32>
+  // CHECK: llvm.func @test()
+  llvm.func @test() -> !llvm.ptr<3> {
+    %0 = llvm.mlir.constant(10 : i32) : i32
+    // CHECK: %[[VAR0:.*]] = llvm.mlir.addressof @__global_alloca_0 : !llvm.ptr<3>
+    // CHECK: %[[VAR1:.*]] = llvm.mlir.addressof @__global_alloca_1 : !llvm.ptr<3>
+    // CHECK: %[[VAR2:.*]] = llvm.mlir.addressof @__global_alloca_2 : !llvm.ptr<3>
+    %1 = llvm.alloca %0 x i32 {alignment = 8 : i64} : (i32) -> !llvm.ptr<3>
+    %2 = llvm.alloca %0 x i32 {alignment = 8 : i64} : (i32) -> !llvm.ptr<3>
+    %3 = llvm.alloca %0 x i32 {alignment = 8 : i64} : (i32) -> !llvm.ptr<3>
+    // CHECK: %[[VAR3:.*]] = llvm.load %[[VAR1:.*]] : !llvm.ptr<3> -> i32
+    // CHECK: %[[VAR4:.*]] = llvm.load %[[VAR2:.*]] : !llvm.ptr<3> -> i32
+    // CHECK: %[[VAR5:.*]] = llvm.add %[[VAR3]], %[[VAR4]] : i32
+    %4 = llvm.load %2 : !llvm.ptr<3> -> i32
+    %5 = llvm.load %3 : !llvm.ptr<3> -> i32
+    %6 = llvm.add %4, %5 : i32
+    // CHECK: llvm.store %[[VAR5]], %[[VAR0]] : i32, !llvm.ptr<3>
+    // CHECK: llvm.return %[[VAR0]] : !llvm.ptr<3>
+    llvm.store %6, %1 : i32, !llvm.ptr<3>
+    llvm.return %1 : !llvm.ptr<3>
+  }
+}

>From fe0973415bd8c1bc86a695bbb0525d32093c83c9 Mon Sep 17 00:00:00 2001
From: "Lee, Sang Ik" <sang.ik.lee at intel.com>
Date: Wed, 25 Feb 2026 23:54:56 +0000
Subject: [PATCH 2/2] Do pattern match checks first.

---
 mlir/lib/Conversion/XeVMToLLVM/XeVMToLLVM.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mlir/lib/Conversion/XeVMToLLVM/XeVMToLLVM.cpp b/mlir/lib/Conversion/XeVMToLLVM/XeVMToLLVM.cpp
index cfbb58581625b..5e9b37e1aeb80 100644
--- a/mlir/lib/Conversion/XeVMToLLVM/XeVMToLLVM.cpp
+++ b/mlir/lib/Conversion/XeVMToLLVM/XeVMToLLVM.cpp
@@ -855,7 +855,6 @@ class AllocaToGlobalPattern : public OpConversionPattern<LLVM::AllocaOp> {
     auto addrSpace = ptrType.getAddressSpace();
     if (addrSpace != 3)
       return failure();
-    auto alignment = op.getAlignment();
     auto val = op.getArraySize();
     APInt cst;
     if (!matchPattern(val, m_ConstantInt(&cst)))
@@ -865,6 +864,7 @@ class AllocaToGlobalPattern : public OpConversionPattern<LLVM::AllocaOp> {
         rewriter.getContext(), op.getElemType(), cst.getZExtValue());
     auto saveIP = rewriter.saveInsertionPoint();
     rewriter.setInsertionPointToStart(moduleOp.getBody());
+    auto alignment = op.getAlignment();
     auto globalVar = LLVM::GlobalOp::create(
         rewriter, loc, globalType, /*isConstant=*/false,
         /*linkage=*/LLVM::Linkage::Internal,



More information about the Mlir-commits mailing list