[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 01:54:29 PDT 2024
https://github.com/Menooker created https://github.com/llvm/llvm-project/pull/92369
Add a new dialect `LibC` to expose some useful features from CPU's standard C library. Currently, only `printf` is added. `printf` is particularly useful in debugging and testing. There is a `gpu.printf` op, but it is missing on CPU.
>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] [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 ®istry);
+} // 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 ®istry) {
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 ®istry) {
+ 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
More information about the Mlir-commits
mailing list