Last active
August 16, 2022 06:36
-
-
Save rednaxelafx/2896df50ab7b60ea0dd0 to your computer and use it in GitHub Desktop.
Comparing different JIT libraries via contrived simple examples
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
// #include <jit/jit-dump.h> | |
#include <jit/jit-plus.h> | |
// Create an example function equivalent to: | |
// int foo(int x, int y, int z) { | |
// return x + y * z; | |
// } | |
jit_function create_example_foo(jit_context& context, int opt_level) { | |
jit_type_t signature = jit_function::signature_helper( | |
jit_type_int, // return type | |
jit_type_int, jit_type_int, jit_type_int, // param types | |
jit_function::end_params); | |
jit_function func(context, signature); | |
func.set_optimization_level(opt_level); | |
func.build_start(); | |
jit_value x = func.get_param(0), | |
y = func.get_param(1), | |
z = func.get_param(2); | |
func.insn_return(x + y * z); // use overloaded operators to build expressions | |
// An equivalent of the above without using the overloaded operators: | |
// jit_value mul = func.insn_mul(y, z); | |
// jit value add = func.insn_add(x, mul); | |
// func.insn_return(add); | |
func.compile(); // force eager compilation | |
func.build_end(); | |
return func; | |
} | |
// Create an example function equivalent to: | |
// int bar(int x, int y, int z) { | |
// return x > 0 ? y : z; | |
// } | |
jit_function create_example_bar(jit_context& context, int opt_level) { | |
jit_type_t signature = jit_function::signature_helper( | |
jit_type_int, // return type | |
jit_type_int, jit_type_int, jit_type_int, // param types | |
jit_function::end_params); | |
jit_function func(context, signature); | |
func.set_optimization_level(opt_level); | |
func.build_start(); | |
jit_label else_label = func.new_label(), | |
after_label = func.new_label(); | |
jit_value x = func.get_param(0), | |
y = func.get_param(1), | |
z = func.get_param(2), | |
zero_const = func.new_constant(0, jit_type_int), | |
temp = func.new_value(jit_type_int); | |
// if part | |
jit_value cond = func.insn_gt(x, zero_const); // cond = x > 0 | |
func.insn_branch_if_not(cond, else_label); // if cond fallthrough else goto else_label | |
// then part | |
func.store(temp, y); // temp = y | |
func.insn_branch(after_label); // goto after_label | |
// else part | |
func.insn_label(else_label); // else_label: | |
func.store(temp, z); // temp = z | |
// after if | |
func.insn_label(after_label); // after_label: | |
func.insn_return(temp); // return temp | |
func.compile(); // force eager compilation | |
func.build_end(); | |
return func; | |
} | |
typedef int (*func_ptr)(int, int, int); | |
// Compile: | |
// clang++ -I<include_path> -L<lib_path> -ljit -ljitplus test_libjit.cc | |
// Run: | |
// DYLD_LIBRARY_PATH=<lib_path> ./a.out | |
int main(int argc, char* argv[]) { | |
// jit_function_get_max_optimization_level() returns 1, no point using a higher level | |
int opt_level = (argc > 0) ? atoi(argv[0]) : 0; | |
jit_context context; | |
jit_function foo_func = create_example_foo(context, opt_level); | |
jit_int x = 2; | |
jit_int y = 5; | |
jit_int z = 8; | |
void* params[] = { &x, &y, &z }; | |
jit_int result; | |
foo_func.apply(params, &result); // call generated code with encapsulated function | |
std::cout << "foo_func.apply(2, 5, 8) = " << result << std::endl; | |
func_ptr fp = (func_ptr) foo_func.closure(); // retrieve the entry point to generated code | |
int result2 = fp(2, 5, 8); // call generated code through normal C syntax | |
std::cout << "fp(2, 5, 8) = " << result2 << std::endl; | |
// jit_dump_function(stdout, func.raw(), "foo"); | |
jit_function bar_func = create_example_bar(context, opt_level); | |
bar_func.apply(params, &result); | |
std::cout << "bar_func(2, 5, 8) = " << result << std::endl; | |
return 0; | |
} | |
/* | |
For example foo(): | |
Optimization level 0 and 1 produce the same code: | |
0x10c02c148: push %rbp | |
0x10c02c149: mov %rsp,%rbp | |
0x10c02c14c: sub $0x20,%rsp | |
0x10c02c150: mov %edi,-0x8(%rbp) | |
0x10c02c153: mov %esi,-0x10(%rbp) | |
0x10c02c156: mov %edx,-0x18(%rbp) | |
0x10c02c159: mov -0x10(%rbp),%eax | |
0x10c02c15c: imul -0x18(%rbp),%eax | |
0x10c02c160: mov -0x8(%rbp),%ecx | |
0x10c02c163: add %ecx,%eax | |
0x10c02c165: mov %rbp,%rsp | |
0x10c02c168: pop %rbp | |
0x10c02c169: retq | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment