All Projects → jmmartinez → Easy Just In Time

jmmartinez / Easy Just In Time

Licence: bsd-3-clause
LLVM Optimization to extract a function, embedded in its intermediate representation in the binary, and execute it using the LLVM Just-In-Time compiler.

Programming Languages

cpp
1120 projects

Labels

Projects that are alternatives of or similar to Easy Just In Time

Llvm Tutorial Standalone
DEPRECATED (Use: https://github.com/llvm-hs/llvm-hs-kaleidoscope )
Stars: ✭ 38 (-89.47%)
Mutual labels:  llvm, jit
Jfs
Constraint solver based on coverage-guided fuzzing
Stars: ✭ 215 (-40.44%)
Mutual labels:  llvm, jit
Leekscript V2
A dynamically typed, compiled just-in-time programming language used in Leek Wars' AIs
Stars: ✭ 46 (-87.26%)
Mutual labels:  llvm, jit
Codegen
Experimental wrapper over LLVM for generating and compiling code at run-time.
Stars: ✭ 362 (+0.28%)
Mutual labels:  llvm, jit
jitmap
LLVM-jitted bitmaps
Stars: ✭ 25 (-93.07%)
Mutual labels:  llvm, jit
Inkwell
It's a New Kind of Wrapper for Exposing LLVM (Safely)
Stars: ✭ 732 (+102.77%)
Mutual labels:  llvm, jit
Jitfromscratch
Example project from my talks in the LLVM Social Berlin and C++ User Group
Stars: ✭ 158 (-56.23%)
Mutual labels:  llvm, jit
Mull
Practical mutation testing tool for C and C++
Stars: ✭ 536 (+48.48%)
Mutual labels:  llvm, jit
Batch-First
A JIT compiled chess engine which traverses the search tree in batches in a best-first manner, allowing for neural network batching, asynchronous GPU use, and vectorized CPU computations.
Stars: ✭ 27 (-92.52%)
Mutual labels:  llvm, jit
adorad
Fast, Expressive, & High-Performance Programming Language for those who dare
Stars: ✭ 54 (-85.04%)
Mutual labels:  llvm, jit
Llvm Hs Examples
Examples for Haskell bindings to LLVM
Stars: ✭ 51 (-85.87%)
Mutual labels:  llvm, jit
Awesome Graal
A curated list of awesome resources for Graal, GraalVM, Truffle and related topics
Stars: ✭ 302 (-16.34%)
Mutual labels:  llvm, jit
FastLua
Lua trace JIT compiler using LLVM-C
Stars: ✭ 22 (-93.91%)
Mutual labels:  llvm, jit
halo
😇 Wholly Adaptive LLVM Optimizer
Stars: ✭ 22 (-93.91%)
Mutual labels:  llvm, jit
dmr c
dmr_C is a C parser and JIT compiler with LLVM, Eclipse OMR and NanoJIT backends
Stars: ✭ 45 (-87.53%)
Mutual labels:  llvm, jit
Cranelift Jit Demo
JIT compiler and runtime for a toy language, using Cranelift
Stars: ✭ 297 (-17.73%)
Mutual labels:  jit
Clangkit
ClangKit provides an Objective-C frontend to LibClang. Source tokenization, diagnostics and fix-its are actually implemented.
Stars: ✭ 330 (-8.59%)
Mutual labels:  llvm
Go Ast Book
📚 《Go语法树入门——开启自制编程语言和编译器之旅》(开源免费图书/Go语言进阶/掌握抽象语法树/Go语言AST/凹语言)
Stars: ✭ 4,034 (+1017.45%)
Mutual labels:  llvm
Clang Power Tools
Bringing clang-tidy magic to Visual Studio C++ developers.
Stars: ✭ 285 (-21.05%)
Mutual labels:  llvm
Wasi Sdk
WASI-enabled WebAssembly C/C++ toolchain
Stars: ✭ 342 (-5.26%)
Mutual labels:  llvm

Easy::jit: A just-in-time compiler for C++

Build Status

About

Easy::jit is a compiler-assisted library that enables simple Just-In-Time code generation for C++ codes.

Talks

Building

First, install clang and LLVM.

apt install llvm-6.0-dev llvm-6.0-tools clang-6.0

Then, configure and compile the project.

cmake -DLLVM_DIR=/usr/lib/llvm-6.0/cmake <path_to_easy_jit_src>
cmake --build .

To build the examples, install the opencv library, and add the flags -DEASY_JIT_EXAMPLE=1 to the cmake command.

To enable benchmarking, install the google benchmark framework, and add the flags -DEASY_JIT_BENCHMARK=1 -DBENCHMARK_DIR=<path_to_google_benchmark_install> to the cmake command.

Everything is ready to go!

Docker

If you want to give only a quick test to the project, everything is provided to use it with docker. To do this, generate a Dockerfile from the current directory using the scripts in <path_to_easy_jit_src>/misc/docker, then generate your docker instance.

python3 <path_to_easy_jit_src>/misc/docker/GenDockerfile.py  <path_to_easy_jit_src>/.travis.yml > Dockerfile
docker build -t easy/test -f Dockerfile
docker run -ti easy/test /bin/bash

Basic usage

Compiling my project with Easy::Jit

Since the Easy::Jit library relies on assistance from the compiler, its mandatory to load a compiler plugin in order to use it. The flag -Xclang -load -Xclang <path_to_easy_jit_build>/bin/EasyJitPass.so loads the plugin.

The included headers require C++14 support, and remember to add the include directories! Use --std=c++14 -I<path_to_easy_jit_src>/cpplib/include.

Finaly, the binary must be linked against the Easy::Jit runtime library, using -L<path_to_easy_jit_build>/bin -lEasyJitRuntime.

Putting all together we get the command bellow.

clang++-6.0 --std=c++14 <my_file.cpp> \
  -Xclang -load -Xclang /path/to/easy/jit/build/bin/bin/EasyJitPass.so \
  -I<path_to_easy_jit_src>/cpplib/include \
  -L<path_to_easy_jit_build>/bin -lEasyJitRuntime

Using Easy::Jit inside my project

Consider the code below from a software that applies image filters on a video stream. In the following sections we are going to adapt it to use the Easy::jit library. The function to optimize is kernel, which applies a mask on the entire image.

The mask, its dimensions and area do not change often, so specializing the function for these parameters seems reasonable. Moreover, the image dimensions and number of channels typically remain constant during the entire execution; however, it is impossible to know their values as they depend on the stream.

static void kernel(const char* mask, unsigned mask_size, unsigned mask_area,
                   const unsigned char* in, unsigned char* out,
                   unsigned rows, unsigned cols, unsigned channels) {
  unsigned mask_middle = (mask_size/2+1);
  unsigned middle = (cols+1)*mask_middle;

  for(unsigned i = 0; i != rows-mask_size; ++i) {
    for(unsigned j = 0; j != cols-mask_size; ++j) {
      for(unsigned ch = 0; ch != channels; ++ch) {

        long out_val = 0;
        for(unsigned ii = 0; ii != mask_size; ++ii) {
          for(unsigned jj = 0; jj != mask_size; ++jj) {
            out_val += mask[ii*mask_size+jj] * in[((i+ii)*cols+j+jj)*channels+ch];
          }
        }
        out[(i*cols+j+middle)*channels+ch] = out_val / mask_area;
      }
    }
  }
}

static void apply_filter(const char *mask, unsigned mask_size, unsigned mask_area, cv::Mat &image, cv::Mat *&out) {
  kernel(mask, mask_size, mask_area, image.ptr(0,0), out->ptr(0,0), image.rows, image.cols, image.channels());
}

The main header for the library is easy/jit.h, where the only core function of the library is exported. This function is called -- guess how? -- easy::jit. We add the corresponding include directive them in the top of the file.

#include <easy/jit.h>

With the call to easy::jit, we specialize the function and obtain a new one taking only two parameters (the input and the output frame).

static void apply_filter(const char *mask, unsigned mask_size, unsigned mask_area, cv::Mat &image, cv::Mat *&out) {
  using namespace std::placeholders;

  auto kernel_opt = easy::jit(kernel, mask, mask_size, mask_area, _1, _2, image.rows, image.cols, image.channels());
  kernel_opt(image.ptr(0,0), out->ptr(0,0));
}

Deducing which functions to expose at runtime

Easy::jit embeds the LLVM bitcode representation of the functions to specialize at runtime in the binary code. To perform this, the library requires access to the implementation of these functions. Easy::jit does an effort to deduce which functions are specialized at runtime, still in many cases this is not possible.

In this case, it's possible to use the EASY_JIT_EXPOSE macro, as shown in the following code,

void EASY_JIT_EXPOSE kernel() { /* ... */ }

or using a regular expression during compilation. The command bellow exports all functions whose name starts with "^kernel".

clang++ ... -mllvm -easy-export="^kernel.*"  ...

Caching

In parallel to the easy/jit.h header, there is easy/code_cache.h which provides a code cache to avoid recompilation of functions that already have been generated.

Bellow we show the code from previous section, but adapted to use a code cache.

#include <easy/code_cache.h>
static void apply_filter(const char *mask, unsigned mask_size, unsigned mask_area, cv::Mat &image, cv::Mat *&out) {
  using namespace std::placeholders;

  static easy::Cache<> cache;
  auto const &kernel_opt = cache.jit(kernel, mask, mask_size, mask_area, _1, _2, image.rows, image.cols, image.channels());
  kernel_opt(image.ptr(0,0), out->ptr(0,0));
}

License

See file LICENSE at the top-level directory of this project.

Thanks

Special thanks to Quarkslab for their support on working in personal projects.

Warriors

Serge Guelton (serge_sans_paille)

Juan Manuel Martinez Caamaño (jmmartinez)

Kavon Farvardin (kavon) author of atJIT

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].