[Mlir-commits] [mlir] [mlir] [Dialect] Add LibC dialect and printf op for CPU (PR #92369)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Thu May 16 02:03:17 PDT 2024


https://github.com/Menooker updated https://github.com/llvm/llvm-project/pull/92369

>From 9b19bb816d225d1bf3ca1236908bb5d0fbc40c17 Mon Sep 17 00:00:00 2001
From: "Mei, Yijie" <yijie.mei at intel.com>
Date: Thu, 16 May 2024 16:43:32 +0800
Subject: [PATCH 1/2] [mlir] [Dialect] Add LibC dialect and printf op for CPU

---
 .../mlir/Conversion/LibCToLLVM/LibCToLLVM.h   |  27 +++
 mlir/include/mlir/Conversion/Passes.h         |   1 +
 mlir/include/mlir/Conversion/Passes.td        |  13 ++
 mlir/include/mlir/Dialect/CMakeLists.txt      |   1 +
 mlir/include/mlir/Dialect/LibC/CMakeLists.txt |   2 +
 mlir/include/mlir/Dialect/LibC/LibC.td        |  55 +++++++
 mlir/include/mlir/Dialect/LibC/LibCDialect.h  |  27 +++
 mlir/include/mlir/InitAllDialects.h           |   2 +
 mlir/lib/Conversion/CMakeLists.txt            |   1 +
 mlir/lib/Conversion/LibCToLLVM/CMakeLists.txt |  18 ++
 mlir/lib/Conversion/LibCToLLVM/LibCToLLVM.cpp | 155 ++++++++++++++++++
 mlir/lib/Dialect/CMakeLists.txt               |   1 +
 mlir/lib/Dialect/LibC/CMakeLists.txt          |  14 ++
 mlir/lib/Dialect/LibC/LibCDialect.cpp         |  31 ++++
 .../Conversion/LibCToLLVM/printf-run.mlir     |  17 ++
 .../Conversion/LibCToLLVM/printf-to-mlir.mlir |  19 +++
 16 files changed, 384 insertions(+)
 create mode 100644 mlir/include/mlir/Conversion/LibCToLLVM/LibCToLLVM.h
 create mode 100644 mlir/include/mlir/Dialect/LibC/CMakeLists.txt
 create mode 100644 mlir/include/mlir/Dialect/LibC/LibC.td
 create mode 100644 mlir/include/mlir/Dialect/LibC/LibCDialect.h
 create mode 100644 mlir/lib/Conversion/LibCToLLVM/CMakeLists.txt
 create mode 100644 mlir/lib/Conversion/LibCToLLVM/LibCToLLVM.cpp
 create mode 100644 mlir/lib/Dialect/LibC/CMakeLists.txt
 create mode 100644 mlir/lib/Dialect/LibC/LibCDialect.cpp
 create mode 100644 mlir/test/Conversion/LibCToLLVM/printf-run.mlir
 create mode 100644 mlir/test/Conversion/LibCToLLVM/printf-to-mlir.mlir

diff --git a/mlir/include/mlir/Conversion/LibCToLLVM/LibCToLLVM.h b/mlir/include/mlir/Conversion/LibCToLLVM/LibCToLLVM.h
new file mode 100644
index 0000000000000..0776c2debe410
--- /dev/null
+++ b/mlir/include/mlir/Conversion/LibCToLLVM/LibCToLLVM.h
@@ -0,0 +1,27 @@
+//===- LibCToLLVM.h - Utils to convert from the libc dialect --------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+#ifndef MLIR_CONVERSION_LIBCTOLLVM_LIBCTOLLVM_H_
+#define MLIR_CONVERSION_LIBCTOLLVM_LIBCTOLLVM_H_
+
+#include "mlir/IR/PatternMatch.h"
+
+namespace mlir {
+class LLVMTypeConverter;
+class RewritePatternSet;
+class Pass;
+#define GEN_PASS_DECL_CONVERTLIBCTOLLVMPASS
+#include "mlir/Conversion/Passes.h.inc"
+
+/// Populate the given list with patterns that convert from LibC to Func.
+void populateLibCToLLVMConversionPatterns(LLVMTypeConverter &converter,
+                                                RewritePatternSet &patterns);
+
+void registerConvertLibCToLLVMInterface(DialectRegistry &registry);
+} // namespace mlir
+
+#endif // MLIR_CONVERSION_LIBCTOLLVM_LIBCTOLLVM_H_
diff --git a/mlir/include/mlir/Conversion/Passes.h b/mlir/include/mlir/Conversion/Passes.h
index 2179ae18ac074..b63be36f14abf 100644
--- a/mlir/include/mlir/Conversion/Passes.h
+++ b/mlir/include/mlir/Conversion/Passes.h
@@ -40,6 +40,7 @@
 #include "mlir/Conversion/GPUToVulkan/ConvertGPUToVulkanPass.h"
 #include "mlir/Conversion/IndexToLLVM/IndexToLLVM.h"
 #include "mlir/Conversion/IndexToSPIRV/IndexToSPIRV.h"
+#include "mlir/Conversion/LibCToLLVM/LibCToLLVM.h"
 #include "mlir/Conversion/LinalgToStandard/LinalgToStandard.h"
 #include "mlir/Conversion/MathToFuncs/MathToFuncs.h"
 #include "mlir/Conversion/MathToLLVM/MathToLLVM.h"
diff --git a/mlir/include/mlir/Conversion/Passes.td b/mlir/include/mlir/Conversion/Passes.td
index e6d678dc1b12b..5244ba415878e 100644
--- a/mlir/include/mlir/Conversion/Passes.td
+++ b/mlir/include/mlir/Conversion/Passes.td
@@ -1356,4 +1356,17 @@ def ConvertVectorToSPIRV : Pass<"convert-vector-to-spirv"> {
   let dependentDialects = ["spirv::SPIRVDialect"];
 }
 
+
+//===----------------------------------------------------------------------===//
+// LibCToLLVM
+//===----------------------------------------------------------------------===//
+
+def ConvertLibCToLLVMPass: Pass<"convert-libc-to-llvm"> {
+  let summary = "Convert libc to LLVM dialect";
+  let description = [{
+    This pass converts supported libc ops to LLVM dialect ops.
+  }];
+  let dependentDialects = ["LLVM::LLVMDialect"];
+}
+
 #endif // MLIR_CONVERSION_PASSES
diff --git a/mlir/include/mlir/Dialect/CMakeLists.txt b/mlir/include/mlir/Dialect/CMakeLists.txt
index 4bd7f12fabf7b..5589c47aa0809 100644
--- a/mlir/include/mlir/Dialect/CMakeLists.txt
+++ b/mlir/include/mlir/Dialect/CMakeLists.txt
@@ -15,6 +15,7 @@ add_subdirectory(Func)
 add_subdirectory(GPU)
 add_subdirectory(Index)
 add_subdirectory(IRDL)
+add_subdirectory(LibC)
 add_subdirectory(Linalg)
 add_subdirectory(LLVMIR)
 add_subdirectory(Math)
diff --git a/mlir/include/mlir/Dialect/LibC/CMakeLists.txt b/mlir/include/mlir/Dialect/LibC/CMakeLists.txt
new file mode 100644
index 0000000000000..80b2fea4aa50f
--- /dev/null
+++ b/mlir/include/mlir/Dialect/LibC/CMakeLists.txt
@@ -0,0 +1,2 @@
+add_mlir_dialect(LibC libc)
+add_mlir_doc(LibC LibC Dialects/ -gen-dialect-doc -dialect=libc)
\ No newline at end of file
diff --git a/mlir/include/mlir/Dialect/LibC/LibC.td b/mlir/include/mlir/Dialect/LibC/LibC.td
new file mode 100644
index 0000000000000..e27e813e5d52c
--- /dev/null
+++ b/mlir/include/mlir/Dialect/LibC/LibC.td
@@ -0,0 +1,55 @@
+//===-- AMX.td - AMX dialect operation definitions *- tablegen -*----------===//
+//
+// 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 defines the basic operations for the libc dialect.
+//
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_DIALECT_LIBC_LIBC
+#define MLIR_DIALECT_LIBC_LIBC
+
+include "mlir/Dialect/LLVMIR/LLVMOpBase.td"
+include "mlir/Interfaces/SideEffectInterfaces.td"
+
+//===----------------------------------------------------------------------===//
+// LibC dialect definition.
+//===----------------------------------------------------------------------===//
+
+def LibC_Dialect : Dialect {
+  let name = "libc";
+  let cppNamespace = "::mlir::libc";
+  let description = [{
+ The dialect provides interfaces for the standard C library functions, to
+ enable users to call them in CPU environments if a valid standard C library
+ (like glibc) is linked. The dialect's ops are designed to be lowered to
+ function calls to the corresponding LibC functions.
+  }];
+}
+
+class LibC_Op<string mnemonic, list<Trait> traits = []> :
+  Op<LibC_Dialect, mnemonic, traits> {}
+
+def LibC_PrintfOp : LibC_Op<"printf", [MemoryEffects<[MemWrite]>]>,
+  Arguments<(ins StrAttr:$format,
+                Variadic<AnyTypeOf<[AnyInteger, Index, AnyFloat]>>:$args)> {
+  let summary = "C-style printf";
+  let description = [{
+    `cpuruntime.printf` takes a literal format string `format` and an arbitrary
+    number of scalar arguments that should be printed.
+
+    The format string is a C-style printf string, subject to any restrictions
+    imposed by the target platform.
+  }];
+  let assemblyFormat = [{
+    $format attr-dict ($args^ `:` type($args))?
+  }];
+}
+
+
+#endif // MLIR_DIALECT_LIBC_LIBC
diff --git a/mlir/include/mlir/Dialect/LibC/LibCDialect.h b/mlir/include/mlir/Dialect/LibC/LibCDialect.h
new file mode 100644
index 0000000000000..98baab3387dba
--- /dev/null
+++ b/mlir/include/mlir/Dialect/LibC/LibCDialect.h
@@ -0,0 +1,27 @@
+//===- LibCDialect.h - MLIR Dialect for LibC ---------------------*- C++ -*-===//
+//
+// 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 declares the dialect for LibC in MLIR.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_DIALECT_LIBC_LIBCDIALECT_H_
+#define MLIR_DIALECT_LIBC_LIBCDIALECT_H_
+
+#include "mlir/Bytecode/BytecodeOpInterface.h"
+#include "mlir/IR/BuiltinTypes.h"
+#include "mlir/IR/Dialect.h"
+#include "mlir/IR/OpDefinition.h"
+#include "mlir/Interfaces/SideEffectInterfaces.h"
+
+#include "mlir/Dialect/LibC/LibCDialect.h.inc"
+
+#define GET_OP_CLASSES
+#include "mlir/Dialect/LibC/LibC.h.inc"
+
+#endif // MLIR_DIALECT_LIBC_LIBCDIALECT_H_
diff --git a/mlir/include/mlir/InitAllDialects.h b/mlir/include/mlir/InitAllDialects.h
index d9db21073e15c..da36d9f9aa057 100644
--- a/mlir/include/mlir/InitAllDialects.h
+++ b/mlir/include/mlir/InitAllDialects.h
@@ -43,6 +43,7 @@
 #include "mlir/Dialect/LLVMIR/LLVMDialect.h"
 #include "mlir/Dialect/LLVMIR/NVVMDialect.h"
 #include "mlir/Dialect/LLVMIR/ROCDLDialect.h"
+#include "mlir/Dialect/LibC/LibCDialect.h"
 #include "mlir/Dialect/Linalg/IR/Linalg.h"
 #include "mlir/Dialect/Linalg/Transforms/AllInterfaces.h"
 #include "mlir/Dialect/Linalg/Transforms/RuntimeOpVerification.h"
@@ -121,6 +122,7 @@ inline void registerAllDialects(DialectRegistry &registry) {
                   gpu::GPUDialect,
                   index::IndexDialect,
                   irdl::IRDLDialect,
+                  libc::LibCDialect,
                   linalg::LinalgDialect,
                   LLVM::LLVMDialect,
                   math::MathDialect,
diff --git a/mlir/lib/Conversion/CMakeLists.txt b/mlir/lib/Conversion/CMakeLists.txt
index 41ab7046b91ce..66178b122745e 100644
--- a/mlir/lib/Conversion/CMakeLists.txt
+++ b/mlir/lib/Conversion/CMakeLists.txt
@@ -29,6 +29,7 @@ add_subdirectory(GPUToSPIRV)
 add_subdirectory(GPUToVulkan)
 add_subdirectory(IndexToLLVM)
 add_subdirectory(IndexToSPIRV)
+add_subdirectory(LibCToLLVM)
 add_subdirectory(LinalgToStandard)
 add_subdirectory(LLVMCommon)
 add_subdirectory(MathToFuncs)
diff --git a/mlir/lib/Conversion/LibCToLLVM/CMakeLists.txt b/mlir/lib/Conversion/LibCToLLVM/CMakeLists.txt
new file mode 100644
index 0000000000000..f73506a22211a
--- /dev/null
+++ b/mlir/lib/Conversion/LibCToLLVM/CMakeLists.txt
@@ -0,0 +1,18 @@
+add_mlir_conversion_library(MLIRLibCToLLVM
+  LibCToLLVM.cpp
+
+  ADDITIONAL_HEADER_DIRS
+  ${MLIR_MAIN_INCLUDE_DIR}/mlir/Conversion/LibCToLLVM
+
+  DEPENDS
+  MLIRConversionPassIncGen
+
+  LINK_COMPONENTS
+  Core
+
+  LINK_LIBS PUBLIC
+  MLIRLLVMCommonConversion
+  MLIRLLVMDialect
+  MLIRLibCDialect
+  MLIRPass
+  )
diff --git a/mlir/lib/Conversion/LibCToLLVM/LibCToLLVM.cpp b/mlir/lib/Conversion/LibCToLLVM/LibCToLLVM.cpp
new file mode 100644
index 0000000000000..29fd57e1653cd
--- /dev/null
+++ b/mlir/lib/Conversion/LibCToLLVM/LibCToLLVM.cpp
@@ -0,0 +1,155 @@
+//===-- LibCToLLVM.cpp - conversion from LibC to Func calls ---------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Conversion/LibCToLLVM/LibCToLLVM.h"
+#include "mlir/Conversion/ConvertToLLVM/ToLLVMInterface.h"
+#include "mlir/Conversion/LLVMCommon/ConversionTarget.h"
+#include "mlir/Conversion/LLVMCommon/Pattern.h"
+#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
+#include "mlir/Dialect/LibC/LibCDialect.h"
+#include "mlir/IR/PatternMatch.h"
+#include "mlir/IR/TypeUtilities.h"
+#include "mlir/Pass/Pass.h"
+#include "mlir/Rewrite/FrozenRewritePatternSet.h"
+#include "mlir/Support/LogicalResult.h"
+#include "mlir/Transforms/GreedyPatternRewriteDriver.h"
+
+namespace mlir {
+
+void populateLibCToLLVMConversionPatterns(LLVMTypeConverter &converter,
+                                          RewritePatternSet &patterns);
+
+#define GEN_PASS_DEF_CONVERTLIBCTOLLVMPASS
+#include "mlir/Conversion/Passes.h.inc"
+
+namespace {
+static const char formatStringPrefix[] = "cpuprintfFormat_";
+
+static LLVM::LLVMFuncOp getOrDefineFunction(ModuleOp &moduleOp,
+                                            const Location loc,
+                                            ConversionPatternRewriter &rewriter,
+                                            StringRef name,
+                                            LLVM::LLVMFunctionType type) {
+  LLVM::LLVMFuncOp ret;
+  if (!(ret = moduleOp.template lookupSymbol<LLVM::LLVMFuncOp>(name))) {
+    ConversionPatternRewriter::InsertionGuard guard(rewriter);
+    rewriter.setInsertionPointToStart(moduleOp.getBody());
+    ret = rewriter.create<LLVM::LLVMFuncOp>(loc, name, type,
+                                            LLVM::Linkage::External);
+  }
+  return ret;
+}
+
+class PrintfRewriter : public ConvertOpToLLVMPattern<libc::PrintfOp> {
+public:
+  using ConvertOpToLLVMPattern<libc::PrintfOp>::ConvertOpToLLVMPattern;
+  LogicalResult
+  matchAndRewrite(libc::PrintfOp op, libc::PrintfOpAdaptor adaptor,
+                  ConversionPatternRewriter &rewriter) const final {
+    auto moduleOp = op->getParentOfType<ModuleOp>();
+    auto loc = op->getLoc();
+    mlir::Type llvmI32 = typeConverter->convertType(rewriter.getI32Type());
+    mlir::Type llvmI64 = typeConverter->convertType(rewriter.getI64Type());
+    mlir::Type llvmI8 = typeConverter->convertType(rewriter.getI8Type());
+    mlir::Type i8Ptr = LLVM::LLVMPointerType::get(op.getContext());
+    auto printfFunc = getOrDefineFunction(
+        moduleOp, loc, rewriter, "printf",
+        LLVM::LLVMFunctionType::get(llvmI32, {i8Ptr}, /*isVarArg*/ true));
+
+    unsigned stringNumber = 0;
+    SmallString<16> stringConstName;
+    do {
+      stringConstName.clear();
+      (formatStringPrefix + Twine(stringNumber++)).toStringRef(stringConstName);
+    } while (moduleOp.lookupSymbol(stringConstName));
+
+    llvm::SmallString<20> formatString(adaptor.getFormat());
+    formatString.push_back('\0'); // Null terminate for C
+    size_t formatStringSize = formatString.size_in_bytes();
+
+    auto globalType = LLVM::LLVMArrayType::get(llvmI8, formatStringSize);
+    LLVM::GlobalOp global;
+    {
+      ConversionPatternRewriter::InsertionGuard guard(rewriter);
+      rewriter.setInsertionPointToStart(moduleOp.getBody());
+      global = rewriter.create<LLVM::GlobalOp>(
+          loc, globalType,
+          /*isConstant=*/true, LLVM::Linkage::Internal, stringConstName,
+          rewriter.getStringAttr(formatString));
+    }
+    Value globalPtr = rewriter.create<LLVM::AddressOfOp>(
+        loc,
+        LLVM::LLVMPointerType::get(rewriter.getContext(),
+                                   global.getAddrSpace()),
+        global.getSymNameAttr());
+    Value stringStart = rewriter.create<LLVM::GEPOp>(
+        loc, i8Ptr, globalType, globalPtr, ArrayRef<LLVM::GEPArg>{0, 0});
+    SmallVector<Value, 5> appendFormatArgs = {stringStart};
+    for (auto arg : adaptor.getArgs()) {
+      if (auto floatType = dyn_cast<FloatType>(arg.getType())) {
+        if (!floatType.isF64())
+          arg = rewriter.create<LLVM::FPExtOp>(
+              loc, typeConverter->convertType(rewriter.getF64Type()), arg);
+      }
+      if (arg.getType().getIntOrFloatBitWidth() != 64)
+        arg = rewriter.create<LLVM::ZExtOp>(loc, llvmI64, arg);
+      appendFormatArgs.push_back(arg);
+    }
+    rewriter.create<LLVM::CallOp>(loc, printfFunc, appendFormatArgs);
+    rewriter.eraseOp(op);
+    return success();
+  }
+};
+
+class ConvertLibCToLLVMPass
+    : public impl::ConvertLibCToLLVMPassBase<ConvertLibCToLLVMPass> {
+public:
+  using Base::Base;
+  void runOnOperation() final {
+    LLVMConversionTarget target(getContext());
+    RewritePatternSet patterns(&getContext());
+    LowerToLLVMOptions options(&getContext());
+    LLVMTypeConverter converter(&getContext(), options);
+    populateLibCToLLVMConversionPatterns(converter, patterns);
+
+    if (failed(applyPartialConversion(getOperation(), target,
+                                      std::move(patterns))))
+      signalPassFailure();
+  }
+};
+
+/// Implement the interface to convert MemRef to LLVM.
+struct ConvertLibCToDialectInterface : public ConvertToLLVMPatternInterface {
+  using ConvertToLLVMPatternInterface::ConvertToLLVMPatternInterface;
+  void loadDependentDialects(MLIRContext *context) const final {
+    context->loadDialect<LLVM::LLVMDialect>();
+  }
+
+  /// Hook for derived dialect interface to provide conversion patterns
+  /// and mark dialect legal for the conversion target.
+  void populateConvertToLLVMConversionPatterns(
+      ConversionTarget &target, LLVMTypeConverter &typeConverter,
+      RewritePatternSet &patterns) const final {
+    populateLibCToLLVMConversionPatterns(typeConverter, patterns);
+  }
+};
+
+} // namespace
+
+void populateLibCToLLVMConversionPatterns(LLVMTypeConverter &converter,
+                                          RewritePatternSet &patterns) {
+  patterns.add<PrintfRewriter>(converter);
+}
+
+void registerConvertLibCToLLVMInterface(DialectRegistry &registry) {
+  registry.addExtension(+[](MLIRContext *ctx, libc::LibCDialect *dialect) {
+    dialect->addInterfaces<ConvertLibCToDialectInterface>();
+  });
+}
+
+} // namespace mlir
diff --git a/mlir/lib/Dialect/CMakeLists.txt b/mlir/lib/Dialect/CMakeLists.txt
index a324ce7f9b19f..684bbb485f877 100644
--- a/mlir/lib/Dialect/CMakeLists.txt
+++ b/mlir/lib/Dialect/CMakeLists.txt
@@ -15,6 +15,7 @@ add_subdirectory(Func)
 add_subdirectory(GPU)
 add_subdirectory(Index)
 add_subdirectory(IRDL)
+add_subdirectory(LibC)
 add_subdirectory(Linalg)
 add_subdirectory(LLVMIR)
 add_subdirectory(Math)
diff --git a/mlir/lib/Dialect/LibC/CMakeLists.txt b/mlir/lib/Dialect/LibC/CMakeLists.txt
new file mode 100644
index 0000000000000..faefaba7e05cb
--- /dev/null
+++ b/mlir/lib/Dialect/LibC/CMakeLists.txt
@@ -0,0 +1,14 @@
+add_mlir_dialect_library(MLIRLibCDialect
+  LibCDialect.cpp
+
+  ADDITIONAL_HEADER_DIRS
+  ${MLIR_MAIN_INCLUDE_DIR}/mlir/Dialect/LibC
+
+  DEPENDS
+  MLIRLibCIncGen
+
+  LINK_LIBS PUBLIC
+  MLIRIR
+  MLIRFuncDialect
+  MLIRSideEffectInterfaces
+  )
diff --git a/mlir/lib/Dialect/LibC/LibCDialect.cpp b/mlir/lib/Dialect/LibC/LibCDialect.cpp
new file mode 100644
index 0000000000000..7b6a710398879
--- /dev/null
+++ b/mlir/lib/Dialect/LibC/LibCDialect.cpp
@@ -0,0 +1,31 @@
+//===- LibCDialect.cpp - MLIR LibC ops implementation -----------------------===//
+//
+// 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 the LibC dialect and its operations.
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Dialect/LibC/LibCDialect.h"
+#include "mlir/Dialect/LLVMIR/LLVMTypes.h"
+#include "mlir/IR/Builders.h"
+#include "mlir/IR/OpImplementation.h"
+#include "mlir/IR/TypeUtilities.h"
+
+using namespace mlir;
+
+#include "mlir/Dialect/LibC/LibCDialect.cpp.inc"
+
+void libc::LibCDialect::initialize() {
+  addOperations<
+#define GET_OP_LIST
+#include "mlir/Dialect/LibC/LibC.cpp.inc"
+      >();
+}
+
+#define GET_OP_CLASSES
+#include "mlir/Dialect/LibC/LibC.cpp.inc"
diff --git a/mlir/test/Conversion/LibCToLLVM/printf-run.mlir b/mlir/test/Conversion/LibCToLLVM/printf-run.mlir
new file mode 100644
index 0000000000000..0b93558f39bf0
--- /dev/null
+++ b/mlir/test/Conversion/LibCToLLVM/printf-run.mlir
@@ -0,0 +1,17 @@
+// RUN: mlir-opt %s --convert-libc-to-llvm --convert-func-to-llvm --convert-arith-to-llvm --convert-cf-to-llvm | mlir-cpu-runner -e main -entry-point-result=void -shared-libs=%mlir_runner_utils,%mlir_c_runner_utils | FileCheck %s
+
+module {
+  func.func @doprint(%t: f32, %t2: i32, %t3: i64) {
+    libc.printf "Hello world %f %d %lld\n" %t, %t2, %t3 : f32, i32, i64
+    return
+  }
+
+  func.func @main() {
+    %c2 = arith.constant 2.0 : f32
+    %c32i = arith.constant 2000000 : i32
+    %c64i = arith.constant 2000000 : i64
+    call @doprint(%c2, %c32i, %c64i) : (f32, i32, i64) -> ()
+    return
+  }
+  // CHECK: Hello world 2.000000 2000000 2000000
+}
\ No newline at end of file
diff --git a/mlir/test/Conversion/LibCToLLVM/printf-to-mlir.mlir b/mlir/test/Conversion/LibCToLLVM/printf-to-mlir.mlir
new file mode 100644
index 0000000000000..67cb2444849a0
--- /dev/null
+++ b/mlir/test/Conversion/LibCToLLVM/printf-to-mlir.mlir
@@ -0,0 +1,19 @@
+// RUN: mlir-opt %s --convert-libc-to-llvm | FileCheck %s
+
+module {
+  // CHECK: llvm.mlir.global internal constant @cpuprintfFormat_0("Hello world %f %d %lld\0A\00") {addr_space = 0 : i32}
+  // CHECK: llvm.func @printf(!llvm.ptr,
+  // CHECK-NEXT: func.func @doprint(%[[ARG0:.*]]: f32, %[[ARG1:.*]]: i32, %[[ARG2:.*]]: i64)
+  func.func @doprint(%t: f32, %t2: i32, %t3: i64) {
+    // CHECK-NEXT: llvm.mlir.addressof
+    // CHECK-DAG: %[[C1:.*]] = llvm.getelementptr
+    // CHECK-SAME: !llvm.ptr, !llvm.array<24 x i8>
+    // CHECK: %[[C2:.*]] = llvm.fpext %[[ARG0]] 
+    // CHECK: %[[C3:.*]] = llvm.zext %[[ARG1]] 
+    // CHECK-NOT: libc.printf
+    // CHECK-NEXT: llvm.call @printf(%[[C1]], %[[C2]], %[[C3]], %[[ARG2]])
+    libc.printf "Hello world %f %d %lld\n" %t, %t2, %t3 : f32, i32, i64
+    return
+  }
+
+}
\ No newline at end of file

>From faf0bed5366e6996c14c20c2f730e4ea39a9e464 Mon Sep 17 00:00:00 2001
From: "Mei, Yijie" <yijie.mei at intel.com>
Date: Thu, 16 May 2024 16:57:07 +0800
Subject: [PATCH 2/2] fix format

---
 mlir/include/mlir/Conversion/LibCToLLVM/LibCToLLVM.h | 2 +-
 mlir/include/mlir/Dialect/LibC/LibCDialect.h         | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/mlir/include/mlir/Conversion/LibCToLLVM/LibCToLLVM.h b/mlir/include/mlir/Conversion/LibCToLLVM/LibCToLLVM.h
index 0776c2debe410..642e8f9052f1d 100644
--- a/mlir/include/mlir/Conversion/LibCToLLVM/LibCToLLVM.h
+++ b/mlir/include/mlir/Conversion/LibCToLLVM/LibCToLLVM.h
@@ -19,7 +19,7 @@ class Pass;
 
 /// Populate the given list with patterns that convert from LibC to Func.
 void populateLibCToLLVMConversionPatterns(LLVMTypeConverter &converter,
-                                                RewritePatternSet &patterns);
+                                          RewritePatternSet &patterns);
 
 void registerConvertLibCToLLVMInterface(DialectRegistry &registry);
 } // namespace mlir
diff --git a/mlir/include/mlir/Dialect/LibC/LibCDialect.h b/mlir/include/mlir/Dialect/LibC/LibCDialect.h
index 98baab3387dba..d0355c8959a47 100644
--- a/mlir/include/mlir/Dialect/LibC/LibCDialect.h
+++ b/mlir/include/mlir/Dialect/LibC/LibCDialect.h
@@ -1,4 +1,4 @@
-//===- LibCDialect.h - MLIR Dialect for LibC ---------------------*- C++ -*-===//
+//===- LibCDialect.h - MLIR Dialect for LibC --------------------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.



More information about the Mlir-commits mailing list