[llvm] [mlir] [MLIR] Add initial convert-memref-to-emitc pass (PR #85389)

Simon Camphausen via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 20 05:48:16 PDT 2024


================
@@ -0,0 +1,94 @@
+//===- MemRefToEmitC.cpp - MemRef to EmitC conversion ---------------------===//
+//
+// Part of the LLVM Project, 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 patterns to convert memref ops into emitc ops.
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Conversion/MemRefToEmitC/MemRefToEmitC.h"
+
+#include "mlir/Dialect/EmitC/IR/EmitC.h"
+#include "mlir/Dialect/MemRef/IR/MemRef.h"
+#include "mlir/IR/Builders.h"
+#include "mlir/IR/PatternMatch.h"
+#include "mlir/Transforms/DialectConversion.h"
+
+using namespace mlir;
+
+namespace {
+struct ConvertAlloca final : public OpConversionPattern<memref::AllocaOp> {
+  using OpConversionPattern::OpConversionPattern;
+
+  LogicalResult
+  matchAndRewrite(memref::AllocaOp op, OpAdaptor operands,
+                  ConversionPatternRewriter &rewriter) const override {
+
+    if (!op.getType().hasStaticShape()) {
+      return rewriter.notifyMatchFailure(
+          op.getLoc(), "cannot transform alloca with dynamic shape");
+    }
+
+    if (op.getAlignment().value_or(1) > 1) {
+      // TODO: Allow alignment if it is not more than the natural alignment
+      // of the C array.
+      return rewriter.notifyMatchFailure(
+          op.getLoc(), "cannot transform alloca with alignment requirement");
+    }
+
+    auto resultTy = getTypeConverter()->convertType(op.getType());
+    auto noInit = emitc::OpaqueAttr::get(getContext(), "");
+    rewriter.replaceOpWithNewOp<emitc::VariableOp>(op, resultTy, noInit);
+    return success();
+  }
+};
+
+struct ConvertLoad final : public OpConversionPattern<memref::LoadOp> {
----------------
simon-camp wrote:

This fails for code like this:
```mlir
func.func @memref_load_store(%in: memref<4x8xf32>, %i: index, %j: index, %val : f32) -> f32 {
  %0 = memref.load %in[%i, %j] : memref<4x8xf32>
  memref.store %val, %in[%i, %j] : memref<4x8xf32>
  return %0 : f32
}
```
Which is lowered to
```mlir
func.func @memref_load_store(%arg0: !emitc.array<4x8xf32>, %arg1: index, %arg2: index, %arg3: f32) -> f32 {
  %0 = emitc.subscript %arg0[%arg1, %arg2] : <4x8xf32>, index, index
  %1 = emitc.subscript %arg0[%arg1, %arg2] : <4x8xf32>, index, index
  emitc.assign %arg3 : f32 to %1 : f32
  return %0 : f32
}
```
and finally emitted as
```c
float memref_load_store(float v1[4][8], size_t v2, size_t v3, float v4) {
  v1[v2][v3] = v4;
  return v1[v2][v3]; // incorrectly returns overridden value
}
```

I think a solution for this is to lower a load into `variable+subscript+assign` ops.

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


More information about the llvm-commits mailing list