1//===- execution_engine.c - Test for the C bindings for the MLIR JIT-------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM
4// Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===----------------------------------------------------------------------===//
9
10/* RUN: mlir-capi-execution-engine-test 2>&1 | FileCheck %s
11 */
12/* REQUIRES: host-supports-jit
13 */
14
15#include "mlir-c/Conversion.h"
16#include "mlir-c/ExecutionEngine.h"
17#include "mlir-c/IR.h"
18#include "mlir-c/RegisterEverything.h"
19
20#include <assert.h>
21#include <math.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25
26static void registerAllUpstreamDialects(MlirContext ctx) {
27 MlirDialectRegistry registry = mlirDialectRegistryCreate();
28 mlirRegisterAllDialects(registry);
29 mlirContextAppendDialectRegistry(ctx, registry);
30 mlirDialectRegistryDestroy(registry);
31}
32
33void lowerModuleToLLVM(MlirContext ctx, MlirModule module) {
34 MlirPassManager pm = mlirPassManagerCreate(ctx);
35 MlirOpPassManager opm = mlirPassManagerGetNestedUnder(
36 pm, mlirStringRefCreateFromCString("func.func"));
37 mlirPassManagerAddOwnedPass(pm, mlirCreateConversionConvertFuncToLLVMPass());
38 mlirOpPassManagerAddOwnedPass(
39 opm, mlirCreateConversionArithToLLVMConversionPass());
40 MlirLogicalResult status =
41 mlirPassManagerRunOnOp(pm, mlirModuleGetOperation(module));
42 if (mlirLogicalResultIsFailure(res: status)) {
43 fprintf(stderr, format: "Unexpected failure running pass pipeline\n");
44 exit(status: 2);
45 }
46 mlirPassManagerDestroy(pm);
47}
48
49// CHECK-LABEL: Running test 'testSimpleExecution'
50void testSimpleExecution(void) {
51 MlirContext ctx = mlirContextCreate();
52 registerAllUpstreamDialects(ctx);
53
54 MlirModule module = mlirModuleCreateParse(
55 context: ctx, module: mlirStringRefCreateFromCString(
56 // clang-format off
57str: "module { \n"
58#ifdef __s390__
59" func.func @add(%arg0 : i32) -> (i32 {llvm.signext}) attributes { llvm.emit_c_interface } { \n"
60#else
61" func.func @add(%arg0 : i32) -> i32 attributes { llvm.emit_c_interface } { \n"
62#endif
63" %res = arith.addi %arg0, %arg0 : i32 \n"
64" return %res : i32 \n"
65" } \n"
66"}"));
67 // clang-format on
68 lowerModuleToLLVM(ctx, module);
69 mlirRegisterAllLLVMTranslations(context: ctx);
70 MlirExecutionEngine jit = mlirExecutionEngineCreate(
71 op: module, /*optLevel=*/2, /*numPaths=*/0, /*sharedLibPaths=*/NULL,
72 /*enableObjectDump=*/false);
73 if (mlirExecutionEngineIsNull(jit)) {
74 fprintf(stderr, format: "Execution engine creation failed");
75 exit(status: 2);
76 }
77 int input = 42;
78 int result = -1;
79 void *args[2] = {&input, &result};
80 if (mlirLogicalResultIsFailure(res: mlirExecutionEngineInvokePacked(
81 jit, name: mlirStringRefCreateFromCString(str: "add"), arguments: args))) {
82 fprintf(stderr, format: "Execution engine creation failed");
83 abort();
84 }
85 // CHECK: Input: 42 Result: 84
86 printf(format: "Input: %d Result: %d\n", input, result);
87 mlirExecutionEngineDestroy(jit);
88 mlirModuleDestroy(module);
89 mlirContextDestroy(context: ctx);
90}
91
92// CHECK-LABEL: Running test 'testOmpCreation'
93void testOmpCreation(void) {
94 MlirContext ctx = mlirContextCreate();
95 registerAllUpstreamDialects(ctx);
96
97 MlirModule module = mlirModuleCreateParse(
98 context: ctx, module: mlirStringRefCreateFromCString(
99 // clang-format off
100str: "module { \n"
101" func.func @main() attributes { llvm.emit_c_interface } { \n"
102" %0 = arith.constant 0 : i32 \n"
103" %1 = arith.constant 1 : i32 \n"
104" %2 = arith.constant 2 : i32 \n"
105" omp.parallel { \n"
106" omp.wsloop { \n"
107" omp.loop_nest (%3) : i32 = (%0) to (%2) step (%1) { \n"
108" omp.yield \n"
109" } \n"
110" } \n"
111" omp.terminator \n"
112" } \n"
113" llvm.return \n"
114" } \n"
115"} \n"
116 ));
117 // clang-format on
118 lowerModuleToLLVM(ctx, module);
119
120 // At this point all operations in the MLIR module have been lowered to the
121 // 'llvm' dialect except 'omp' operations. The goal of this test is
122 // guaranteeing that the execution engine C binding has registered OpenMP
123 // translations and therefore does not fail when it encounters 'omp' ops.
124 // We don't attempt to run the engine, since that would force us to link
125 // against the OpenMP library.
126 MlirExecutionEngine jit = mlirExecutionEngineCreate(
127 op: module, /*optLevel=*/2, /*numPaths=*/0, /*sharedLibPaths=*/NULL,
128 /*enableObjectDump=*/false);
129 if (mlirExecutionEngineIsNull(jit)) {
130 fprintf(stderr, format: "Engine creation failed with OpenMP");
131 exit(status: 2);
132 }
133 // CHECK: Engine creation succeeded with OpenMP
134 printf(format: "Engine creation succeeded with OpenMP\n");
135 mlirExecutionEngineDestroy(jit);
136 mlirModuleDestroy(module);
137 mlirContextDestroy(context: ctx);
138}
139
140int main(void) {
141
142#define _STRINGIFY(x) #x
143#define STRINGIFY(x) _STRINGIFY(x)
144#define TEST(test) \
145 printf("Running test '" STRINGIFY(test) "'\n"); \
146 test();
147
148 TEST(testSimpleExecution);
149 TEST(testOmpCreation);
150 return 0;
151}
152

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

source code of mlir/test/CAPI/execution_engine.c