xref: /llvm-project/mlir/test/CAPI/execution_engine.c (revision 0d9dc421143a0acd414a23f343b555c965a471f1)
186c8a785SMehdi Amini //===- execution_engine.c - Test for the C bindings for the MLIR JIT-------===//
286c8a785SMehdi Amini //
386c8a785SMehdi Amini // Part of the LLVM Project, under the Apache License v2.0 with LLVM
486c8a785SMehdi Amini // Exceptions.
586c8a785SMehdi Amini // See https://llvm.org/LICENSE.txt for license information.
686c8a785SMehdi Amini // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
786c8a785SMehdi Amini //
886c8a785SMehdi Amini //===----------------------------------------------------------------------===//
986c8a785SMehdi Amini 
1086c8a785SMehdi Amini /* RUN: mlir-capi-execution-engine-test 2>&1 | FileCheck %s
1186c8a785SMehdi Amini  */
12ca98e0ddSRainer Orth /* REQUIRES: host-supports-jit
135a68a85dSMehdi Amini  */
1486c8a785SMehdi Amini 
1586c8a785SMehdi Amini #include "mlir-c/Conversion.h"
1686c8a785SMehdi Amini #include "mlir-c/ExecutionEngine.h"
1786c8a785SMehdi Amini #include "mlir-c/IR.h"
185e83a5b4SStella Laurenzo #include "mlir-c/RegisterEverything.h"
1986c8a785SMehdi Amini 
2086c8a785SMehdi Amini #include <assert.h>
2186c8a785SMehdi Amini #include <math.h>
2286c8a785SMehdi Amini #include <stdio.h>
2386c8a785SMehdi Amini #include <stdlib.h>
2486c8a785SMehdi Amini #include <string.h>
2586c8a785SMehdi Amini 
265e83a5b4SStella Laurenzo static void registerAllUpstreamDialects(MlirContext ctx) {
275e83a5b4SStella Laurenzo   MlirDialectRegistry registry = mlirDialectRegistryCreate();
285e83a5b4SStella Laurenzo   mlirRegisterAllDialects(registry);
295e83a5b4SStella Laurenzo   mlirContextAppendDialectRegistry(ctx, registry);
305e83a5b4SStella Laurenzo   mlirDialectRegistryDestroy(registry);
315e83a5b4SStella Laurenzo }
325e83a5b4SStella Laurenzo 
3386c8a785SMehdi Amini void lowerModuleToLLVM(MlirContext ctx, MlirModule module) {
3486c8a785SMehdi Amini   MlirPassManager pm = mlirPassManagerCreate(ctx);
35a54f4eaeSMogball   MlirOpPassManager opm = mlirPassManagerGetNestedUnder(
3636550692SRiver Riddle       pm, mlirStringRefCreateFromCString("func.func"));
375dc34eb3STobias Gysi   mlirPassManagerAddOwnedPass(pm, mlirCreateConversionConvertFuncToLLVMPass());
38b1ce63bbSMichele Scuttari   mlirOpPassManagerAddOwnedPass(
39abc362a1SJakub Kuderski       opm, mlirCreateConversionArithToLLVMConversionPass());
406f5590caSrkayaith   MlirLogicalResult status =
416f5590caSrkayaith       mlirPassManagerRunOnOp(pm, mlirModuleGetOperation(module));
4286c8a785SMehdi Amini   if (mlirLogicalResultIsFailure(status)) {
4386c8a785SMehdi Amini     fprintf(stderr, "Unexpected failure running pass pipeline\n");
4486c8a785SMehdi Amini     exit(2);
4586c8a785SMehdi Amini   }
4686c8a785SMehdi Amini   mlirPassManagerDestroy(pm);
4786c8a785SMehdi Amini }
4886c8a785SMehdi Amini 
4986c8a785SMehdi Amini // CHECK-LABEL: Running test 'testSimpleExecution'
505d91f79fSTom Eccles void testSimpleExecution(void) {
5186c8a785SMehdi Amini   MlirContext ctx = mlirContextCreate();
525e83a5b4SStella Laurenzo   registerAllUpstreamDialects(ctx);
535e83a5b4SStella Laurenzo 
5486c8a785SMehdi Amini   MlirModule module = mlirModuleCreateParse(
5586c8a785SMehdi Amini       ctx, mlirStringRefCreateFromCString(
5686c8a785SMehdi Amini                // clang-format off
5786c8a785SMehdi Amini "module {                                                                    \n"
58*0d9dc421SJonas Paulsson #ifdef __s390__
59*0d9dc421SJonas Paulsson "  func.func @add(%arg0 : i32) -> (i32 {llvm.signext}) attributes { llvm.emit_c_interface } {     \n"
60*0d9dc421SJonas Paulsson #else
610fd3a1ceSRiver Riddle "  func.func @add(%arg0 : i32) -> i32 attributes { llvm.emit_c_interface } {     \n"
62*0d9dc421SJonas Paulsson #endif
63a54f4eaeSMogball "    %res = arith.addi %arg0, %arg0 : i32                                        \n"
6486c8a785SMehdi Amini "    return %res : i32                                                           \n"
6586c8a785SMehdi Amini "  }                                                                             \n"
6686c8a785SMehdi Amini "}"));
6786c8a785SMehdi Amini   // clang-format on
6886c8a785SMehdi Amini   lowerModuleToLLVM(ctx, module);
6986c8a785SMehdi Amini   mlirRegisterAllLLVMTranslations(ctx);
70c8b8e8e0SUday Bondhugula   MlirExecutionEngine jit = mlirExecutionEngineCreate(
7195c083f5SDenys Shabalin       module, /*optLevel=*/2, /*numPaths=*/0, /*sharedLibPaths=*/NULL,
7295c083f5SDenys Shabalin       /*enableObjectDump=*/false);
7386c8a785SMehdi Amini   if (mlirExecutionEngineIsNull(jit)) {
7486c8a785SMehdi Amini     fprintf(stderr, "Execution engine creation failed");
7586c8a785SMehdi Amini     exit(2);
7686c8a785SMehdi Amini   }
7786c8a785SMehdi Amini   int input = 42;
7886c8a785SMehdi Amini   int result = -1;
7986c8a785SMehdi Amini   void *args[2] = {&input, &result};
8086c8a785SMehdi Amini   if (mlirLogicalResultIsFailure(mlirExecutionEngineInvokePacked(
8186c8a785SMehdi Amini           jit, mlirStringRefCreateFromCString("add"), args))) {
8286c8a785SMehdi Amini     fprintf(stderr, "Execution engine creation failed");
8386c8a785SMehdi Amini     abort();
8486c8a785SMehdi Amini   }
8586c8a785SMehdi Amini   // CHECK: Input: 42 Result: 84
8686c8a785SMehdi Amini   printf("Input: %d Result: %d\n", input, result);
8786c8a785SMehdi Amini   mlirExecutionEngineDestroy(jit);
8886c8a785SMehdi Amini   mlirModuleDestroy(module);
8986c8a785SMehdi Amini   mlirContextDestroy(ctx);
9086c8a785SMehdi Amini }
9186c8a785SMehdi Amini 
92db7cc034SRafael Ubal Tena // CHECK-LABEL: Running test 'testOmpCreation'
93db7cc034SRafael Ubal Tena void testOmpCreation(void) {
94db7cc034SRafael Ubal Tena   MlirContext ctx = mlirContextCreate();
95db7cc034SRafael Ubal Tena   registerAllUpstreamDialects(ctx);
96db7cc034SRafael Ubal Tena 
97db7cc034SRafael Ubal Tena   MlirModule module = mlirModuleCreateParse(
98db7cc034SRafael Ubal Tena       ctx, mlirStringRefCreateFromCString(
99db7cc034SRafael Ubal Tena                // clang-format off
100db7cc034SRafael Ubal Tena "module {                                                                       \n"
101db7cc034SRafael Ubal Tena "  func.func @main() attributes { llvm.emit_c_interface } {                     \n"
102db7cc034SRafael Ubal Tena "    %0 = arith.constant 0 : i32                                                \n"
103db7cc034SRafael Ubal Tena "    %1 = arith.constant 1 : i32                                                \n"
104db7cc034SRafael Ubal Tena "    %2 = arith.constant 2 : i32                                                \n"
105db7cc034SRafael Ubal Tena "    omp.parallel {                                                             \n"
10607e6c160SSergio Afonso "      omp.wsloop {                                                             \n"
10707e6c160SSergio Afonso "        omp.loop_nest (%3) : i32 = (%0) to (%2) step (%1) {                    \n"
108db7cc034SRafael Ubal Tena "          omp.yield                                                            \n"
109db7cc034SRafael Ubal Tena "        }                                                                      \n"
110db7cc034SRafael Ubal Tena "      }                                                                        \n"
11107e6c160SSergio Afonso "      omp.terminator                                                           \n"
11207e6c160SSergio Afonso "    }                                                                          \n"
113db7cc034SRafael Ubal Tena "    llvm.return                                                                \n"
114db7cc034SRafael Ubal Tena "  }                                                                            \n"
115db7cc034SRafael Ubal Tena "}                                                                              \n"
116db7cc034SRafael Ubal Tena       ));
117db7cc034SRafael Ubal Tena   // clang-format on
118db7cc034SRafael Ubal Tena   lowerModuleToLLVM(ctx, module);
119db7cc034SRafael Ubal Tena 
120db7cc034SRafael Ubal Tena   // At this point all operations in the MLIR module have been lowered to the
121db7cc034SRafael Ubal Tena   // 'llvm' dialect except 'omp' operations. The goal of this test is
122db7cc034SRafael Ubal Tena   // guaranteeing that the execution engine C binding has registered OpenMP
123db7cc034SRafael Ubal Tena   // translations and therefore does not fail when it encounters 'omp' ops.
124db7cc034SRafael Ubal Tena   // We don't attempt to run the engine, since that would force us to link
125db7cc034SRafael Ubal Tena   // against the OpenMP library.
126db7cc034SRafael Ubal Tena   MlirExecutionEngine jit = mlirExecutionEngineCreate(
127db7cc034SRafael Ubal Tena       module, /*optLevel=*/2, /*numPaths=*/0, /*sharedLibPaths=*/NULL,
128db7cc034SRafael Ubal Tena       /*enableObjectDump=*/false);
129db7cc034SRafael Ubal Tena   if (mlirExecutionEngineIsNull(jit)) {
130db7cc034SRafael Ubal Tena     fprintf(stderr, "Engine creation failed with OpenMP");
131db7cc034SRafael Ubal Tena     exit(2);
132db7cc034SRafael Ubal Tena   }
133db7cc034SRafael Ubal Tena   // CHECK: Engine creation succeeded with OpenMP
134db7cc034SRafael Ubal Tena   printf("Engine creation succeeded with OpenMP\n");
135db7cc034SRafael Ubal Tena   mlirExecutionEngineDestroy(jit);
136db7cc034SRafael Ubal Tena   mlirModuleDestroy(module);
137db7cc034SRafael Ubal Tena   mlirContextDestroy(ctx);
138db7cc034SRafael Ubal Tena }
139db7cc034SRafael Ubal Tena 
1405d91f79fSTom Eccles int main(void) {
14186c8a785SMehdi Amini 
14286c8a785SMehdi Amini #define _STRINGIFY(x) #x
14386c8a785SMehdi Amini #define STRINGIFY(x) _STRINGIFY(x)
14486c8a785SMehdi Amini #define TEST(test)                                                             \
14586c8a785SMehdi Amini   printf("Running test '" STRINGIFY(test) "'\n");                              \
14686c8a785SMehdi Amini   test();
14786c8a785SMehdi Amini 
14886c8a785SMehdi Amini   TEST(testSimpleExecution);
149db7cc034SRafael Ubal Tena   TEST(testOmpCreation);
15086c8a785SMehdi Amini   return 0;
15186c8a785SMehdi Amini }
152