[Mlir-commits] [mlir] [mlir][EmitC]Expand the MemRefToEmitC pass - Lowering `AllocOp` (PR #148257)

Jaden Angella llvmlistbot at llvm.org
Thu Jul 24 21:20:53 PDT 2025


================
@@ -77,6 +81,95 @@ struct ConvertAlloca final : public OpConversionPattern<memref::AllocaOp> {
   }
 };
 
+struct ConvertAlloc final : public OpConversionPattern<memref::AllocOp> {
+  using OpConversionPattern::OpConversionPattern;
+  LogicalResult
+  matchAndRewrite(memref::AllocOp allocOp, OpAdaptor operands,
+                  ConversionPatternRewriter &rewriter) const override {
+    mlir::Location loc = allocOp.getLoc();
+    MemRefType memrefType = allocOp.getType();
+    if (!memrefType.hasStaticShape()) {
+      // TODO: Handle Dynamic shapes in the future. If the size
+      // of the allocation is the result of some function, we could
+      // potentially evaluate the function and use the result in the call to
+      // allocate.
+      return rewriter.notifyMatchFailure(
+          loc, "cannot transform alloc with dynamic shape");
+    }
+
+    mlir::Type sizeTType = mlir::emitc::SizeTType::get(rewriter.getContext());
+    Type elementType = memrefType.getElementType();
+    mlir::emitc::CallOpaqueOp sizeofElementOp =
+        rewriter.create<mlir::emitc::CallOpaqueOp>(
+            loc, sizeTType, rewriter.getStringAttr("sizeof"),
+            mlir::ValueRange{},
+            mlir::ArrayAttr::get(rewriter.getContext(),
+                                 {mlir::TypeAttr::get(elementType)}));
+    mlir::Value sizeofElement = sizeofElementOp.getResult(0);
+
+    unsigned int elementWidth = elementType.getIntOrFloatBitWidth();
+    IntegerAttr indexAttr = rewriter.getIndexAttr(elementWidth);
+
+    mlir::Value numElements;
+    numElements = rewriter.create<emitc::ConstantOp>(
+        loc, rewriter.getIndexType(), indexAttr);
+    mlir::Value totalSizeBytes = rewriter.create<emitc::MulOp>(
+        loc, sizeTType, sizeofElement, numElements);
+
+    emitc::CallOpaqueOp allocCall;
+    StringAttr allocFunctionName = allocOp.getAlignment()
+                                       ? rewriter.getStringAttr("aligned_alloc")
+                                       : rewriter.getStringAttr("malloc");
+    mlir::Value alignmentValue;
+    if (allocOp.getAlignment()) {
+      alignmentValue = rewriter.create<emitc::ConstantOp>(
+          loc, sizeTType,
+          rewriter.getIntegerAttr(
+              rewriter.getIndexType(),
+              alignedAllocationGetAlignment(allocOp, elementWidth)));
+    }
+
+    SmallVector<mlir::Value, 2> argsVec;
+    if (allocOp.getAlignment())
+      argsVec.push_back(alignmentValue);
+    argsVec.push_back(totalSizeBytes);
+    mlir::ValueRange args(argsVec);
+
+    allocCall = rewriter.create<emitc::CallOpaqueOp>(
+        loc,
+        emitc::PointerType::get(
+            mlir::emitc::OpaqueType::get(rewriter.getContext(), "void")),
+        allocFunctionName, args);
+
+    emitc::PointerType targetPointerType = emitc::PointerType::get(elementType);
+    emitc::CastOp castOp = rewriter.create<emitc::CastOp>(
+        loc, targetPointerType, allocCall.getResult(0));
+
+    rewriter.replaceOp(allocOp, castOp);
+    return success();
+  }
+
+  /// The minimum alignment to use with aligned_alloc (has to be a power of 2).
+  static constexpr uint64_t kMinAlignedAllocAlignment = 16UL;
+
+  /// Computes the alignment for aligned_alloc used to allocate the buffer for
+  /// the memory allocation op.
+  ///
+  /// Aligned_alloc requires the allocation size to be a power of two, and the
+  /// allocation size to be a multiple of the alignment.
+  int64_t alignedAllocationGetAlignment(memref::AllocOp op,
+                                        unsigned int elementWidth) const {
+    if (std::optional<uint64_t> alignment = op.getAlignment())
----------------
Jaddyen wrote:

This is true!
I can simply get the alignment without further checks

https://github.com/llvm/llvm-project/pull/148257


More information about the Mlir-commits mailing list