mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2024-11-26 15:32:05 +00:00
Use LLVM new pass manager for wamrc (#978)
Use LLVM new pass manager for wamrc to replace the legacy pass manger, so as to gain better performance and reduce the compilation time. Reference links: - https://llvm.org/docs/NewPassManager.html - https://blog.llvm.org/posts/2021-03-26-the-new-pass-manager And add an option to use the legacy pm mode when building wamrc: cmake .. -DWAMR_BUILD_LLVM_LEGACY_PM=1 For JIT mode, keep it unchanged as it only runs several function passes and using new pass manager will increase the compilation time. And refactor the codes of applying LLVM passes.
This commit is contained in:
parent
7636d86a76
commit
5631a2aa18
|
@ -131,9 +131,9 @@ else ()
|
||||||
endif ()
|
endif ()
|
||||||
if (WAMR_BUILD_JIT EQUAL 1)
|
if (WAMR_BUILD_JIT EQUAL 1)
|
||||||
if (WAMR_BUILD_LAZY_JIT EQUAL 1)
|
if (WAMR_BUILD_LAZY_JIT EQUAL 1)
|
||||||
message (" WAMR Lazy JIT enabled")
|
message (" WAMR LLVM Orc Lazy JIT enabled")
|
||||||
else ()
|
else ()
|
||||||
message (" WAMR MC JIT enabled")
|
message (" WAMR LLVM MC JIT enabled")
|
||||||
endif ()
|
endif ()
|
||||||
else ()
|
else ()
|
||||||
message (" WAMR JIT disabled")
|
message (" WAMR JIT disabled")
|
||||||
|
|
|
@ -98,6 +98,14 @@
|
||||||
#define WASM_ENABLE_WAMR_COMPILER 0
|
#define WASM_ENABLE_WAMR_COMPILER 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if WASM_ENABLE_WAMR_COMPILER != 0
|
||||||
|
#ifndef WASM_ENABLE_LLVM_LEGACY_PM
|
||||||
|
/* Whether to use LLVM legacy pass manager when building wamrc,
|
||||||
|
by default it is disabled and LLVM new pass manager is used */
|
||||||
|
#define WASM_ENABLE_LLVM_LEGACY_PM 0
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef WASM_ENABLE_LIBC_BUILTIN
|
#ifndef WASM_ENABLE_LIBC_BUILTIN
|
||||||
#define WASM_ENABLE_LIBC_BUILTIN 0
|
#define WASM_ENABLE_LIBC_BUILTIN 0
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -231,20 +231,6 @@ WASM_DEFINE_VEC_OWN(module, wasm_module_delete_internal)
|
||||||
WASM_DEFINE_VEC_OWN(store, wasm_store_delete)
|
WASM_DEFINE_VEC_OWN(store, wasm_store_delete)
|
||||||
WASM_DEFINE_VEC_OWN(valtype, wasm_valtype_delete)
|
WASM_DEFINE_VEC_OWN(valtype, wasm_valtype_delete)
|
||||||
|
|
||||||
/* conflicting declaration between aot_export.h and aot.h */
|
|
||||||
#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_JIT != 0 && WASM_ENABLE_LAZY_JIT == 0
|
|
||||||
bool
|
|
||||||
aot_compile_wasm_file_init();
|
|
||||||
|
|
||||||
void
|
|
||||||
aot_compile_wasm_file_destroy();
|
|
||||||
|
|
||||||
uint8 *
|
|
||||||
aot_compile_wasm_file(const uint8 *wasm_file_buf, uint32 wasm_file_size,
|
|
||||||
uint32 opt_level, uint32 size_level, char *error_buf,
|
|
||||||
uint32 error_buf_size, uint32 *p_aot_file_size);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Runtime Environment */
|
/* Runtime Environment */
|
||||||
own wasm_config_t *
|
own wasm_config_t *
|
||||||
wasm_config_new(void)
|
wasm_config_new(void)
|
||||||
|
@ -266,10 +252,6 @@ wasm_engine_delete_internal(wasm_engine_t *engine)
|
||||||
wasm_runtime_free(engine);
|
wasm_runtime_free(engine);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_JIT != 0 && WASM_ENABLE_LAZY_JIT == 0
|
|
||||||
aot_compile_wasm_file_destroy();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
wasm_runtime_destroy();
|
wasm_runtime_destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -317,12 +299,6 @@ wasm_engine_new_internal(mem_alloc_type_t type, const MemAllocOption *opts)
|
||||||
bh_log_set_verbose_level(3);
|
bh_log_set_verbose_level(3);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_JIT != 0 && WASM_ENABLE_LAZY_JIT == 0
|
|
||||||
if (!aot_compile_wasm_file_init()) {
|
|
||||||
goto failed;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* create wasm_engine_t */
|
/* create wasm_engine_t */
|
||||||
if (!(engine = malloc_internal(sizeof(wasm_engine_t)))) {
|
if (!(engine = malloc_internal(sizeof(wasm_engine_t)))) {
|
||||||
goto failed;
|
goto failed;
|
||||||
|
@ -1820,10 +1796,6 @@ wasm_module_new(wasm_store_t *store, const wasm_byte_vec_t *binary)
|
||||||
char error_buf[128] = { 0 };
|
char error_buf[128] = { 0 };
|
||||||
wasm_module_ex_t *module_ex = NULL;
|
wasm_module_ex_t *module_ex = NULL;
|
||||||
PackageType pkg_type;
|
PackageType pkg_type;
|
||||||
#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_JIT != 0 && WASM_ENABLE_LAZY_JIT == 0
|
|
||||||
uint8 *aot_file_buf = NULL;
|
|
||||||
uint32 aot_file_size;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bh_assert(singleton_engine);
|
bh_assert(singleton_engine);
|
||||||
|
|
||||||
|
@ -1858,33 +1830,12 @@ wasm_module_new(wasm_store_t *store, const wasm_byte_vec_t *binary)
|
||||||
|
|
||||||
INIT_VEC(module_ex->binary, wasm_byte_vec_new, binary->size, binary->data);
|
INIT_VEC(module_ex->binary, wasm_byte_vec_new, binary->size, binary->data);
|
||||||
|
|
||||||
#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_JIT != 0 && WASM_ENABLE_LAZY_JIT == 0
|
module_ex->module_comm_rt = wasm_runtime_load(
|
||||||
if (Wasm_Module_Bytecode == pkg_type) {
|
(uint8 *)module_ex->binary->data, (uint32)module_ex->binary->size,
|
||||||
if (!(aot_file_buf = aot_compile_wasm_file(
|
error_buf, (uint32)sizeof(error_buf));
|
||||||
(uint8 *)module_ex->binary->data,
|
if (!(module_ex->module_comm_rt)) {
|
||||||
(uint32)module_ex->binary->size, 3, 3, error_buf,
|
LOG_ERROR(error_buf);
|
||||||
(uint32)sizeof(error_buf), &aot_file_size))) {
|
goto failed;
|
||||||
LOG_ERROR(error_buf);
|
|
||||||
goto failed;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(module_ex->module_comm_rt =
|
|
||||||
wasm_runtime_load(aot_file_buf, aot_file_size, error_buf,
|
|
||||||
(uint32)sizeof(error_buf)))) {
|
|
||||||
LOG_ERROR(error_buf);
|
|
||||||
goto failed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
module_ex->module_comm_rt = wasm_runtime_load(
|
|
||||||
(uint8 *)module_ex->binary->data, (uint32)module_ex->binary->size,
|
|
||||||
error_buf, (uint32)sizeof(error_buf));
|
|
||||||
if (!(module_ex->module_comm_rt)) {
|
|
||||||
LOG_ERROR(error_buf);
|
|
||||||
goto failed;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add it to a watching list in store */
|
/* add it to a watching list in store */
|
||||||
|
|
|
@ -2537,6 +2537,145 @@ fail:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
veriy_module(AOTCompContext *comp_ctx)
|
||||||
|
{
|
||||||
|
char *msg = NULL;
|
||||||
|
bool ret;
|
||||||
|
|
||||||
|
#if WASM_ENABLE_LAZY_JIT == 0
|
||||||
|
ret = LLVMVerifyModule(comp_ctx->module, LLVMPrintMessageAction, &msg);
|
||||||
|
if (!ret && msg) {
|
||||||
|
if (msg[0] != '\0') {
|
||||||
|
aot_set_last_error(msg);
|
||||||
|
LLVMDisposeMessage(msg);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
LLVMDisposeMessage(msg);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
uint32 i;
|
||||||
|
|
||||||
|
for (i = 0; i < comp_ctx->func_ctx_count; i++) {
|
||||||
|
ret = LLVMVerifyModule(comp_ctx->modules[i], LLVMPrintMessageAction,
|
||||||
|
&msg);
|
||||||
|
if (!ret && msg) {
|
||||||
|
if (msg[0] != '\0') {
|
||||||
|
aot_set_last_error(msg);
|
||||||
|
LLVMDisposeMessage(msg);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
LLVMDisposeMessage(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
apply_func_passes(AOTCompContext *comp_ctx)
|
||||||
|
{
|
||||||
|
LLVMPassManagerRef pass_mgr;
|
||||||
|
uint32 i;
|
||||||
|
|
||||||
|
#if WASM_ENABLE_LAZY_JIT == 0
|
||||||
|
pass_mgr = LLVMCreateFunctionPassManagerForModule(comp_ctx->module);
|
||||||
|
#else
|
||||||
|
pass_mgr = LLVMCreatePassManager();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!pass_mgr) {
|
||||||
|
aot_set_last_error("create LLVM pass manager failed.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
LLVMAddPromoteMemoryToRegisterPass(pass_mgr);
|
||||||
|
LLVMAddInstructionCombiningPass(pass_mgr);
|
||||||
|
LLVMAddCFGSimplificationPass(pass_mgr);
|
||||||
|
LLVMAddJumpThreadingPass(pass_mgr);
|
||||||
|
#if LLVM_VERSION_MAJOR < 12
|
||||||
|
LLVMAddConstantPropagationPass(pass_mgr);
|
||||||
|
#endif
|
||||||
|
LLVMAddIndVarSimplifyPass(pass_mgr);
|
||||||
|
|
||||||
|
if (!comp_ctx->is_jit_mode) {
|
||||||
|
/* Put Vectorize passes before GVN/LICM passes as the former
|
||||||
|
might gain more performance improvement and the latter might
|
||||||
|
break the optimizations for the former */
|
||||||
|
LLVMAddLoopVectorizePass(pass_mgr);
|
||||||
|
LLVMAddSLPVectorizePass(pass_mgr);
|
||||||
|
LLVMAddLoopRotatePass(pass_mgr);
|
||||||
|
LLVMAddLoopUnswitchPass(pass_mgr);
|
||||||
|
LLVMAddInstructionCombiningPass(pass_mgr);
|
||||||
|
LLVMAddCFGSimplificationPass(pass_mgr);
|
||||||
|
if (!comp_ctx->enable_thread_mgr) {
|
||||||
|
/* These two passes may destroy the volatile semantics,
|
||||||
|
disable them when building as multi-thread mode */
|
||||||
|
LLVMAddGVNPass(pass_mgr);
|
||||||
|
LLVMAddLICMPass(pass_mgr);
|
||||||
|
LLVMAddInstructionCombiningPass(pass_mgr);
|
||||||
|
LLVMAddCFGSimplificationPass(pass_mgr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if WASM_ENABLE_LAZY_JIT == 0
|
||||||
|
LLVMInitializeFunctionPassManager(pass_mgr);
|
||||||
|
for (i = 0; i < comp_ctx->func_ctx_count; i++) {
|
||||||
|
LLVMRunFunctionPassManager(pass_mgr, comp_ctx->func_ctxes[i]->func);
|
||||||
|
}
|
||||||
|
LLVMFinalizeFunctionPassManager(pass_mgr);
|
||||||
|
#else
|
||||||
|
for (i = 0; i < comp_ctx->func_ctx_count; i++) {
|
||||||
|
LLVMRunPassManager(pass_mgr, comp_ctx->modules[i]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
LLVMDisposePassManager(pass_mgr);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if WASM_ENABLE_LLVM_LEGACY_PM != 0
|
||||||
|
static bool
|
||||||
|
apply_lto_passes(AOTCompContext *comp_ctx)
|
||||||
|
{
|
||||||
|
LLVMPassManagerRef common_pass_mgr;
|
||||||
|
LLVMPassManagerBuilderRef pass_mgr_builder;
|
||||||
|
#if WASM_ENABLE_LAZY_JIT != 0
|
||||||
|
uint32 i;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!(common_pass_mgr = LLVMCreatePassManager())) {
|
||||||
|
aot_set_last_error("create LLVM pass manager failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(pass_mgr_builder = LLVMPassManagerBuilderCreate())) {
|
||||||
|
aot_set_last_error("create LLVM pass manager builder failed");
|
||||||
|
LLVMDisposePassManager(common_pass_mgr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
LLVMPassManagerBuilderSetOptLevel(pass_mgr_builder, comp_ctx->opt_level);
|
||||||
|
LLVMPassManagerBuilderPopulateModulePassManager(pass_mgr_builder,
|
||||||
|
common_pass_mgr);
|
||||||
|
LLVMPassManagerBuilderPopulateLTOPassManager(pass_mgr_builder,
|
||||||
|
common_pass_mgr, true, true);
|
||||||
|
|
||||||
|
#if WASM_ENABLE_LAZY_JIT == 0
|
||||||
|
LLVMRunPassManager(common_pass_mgr, comp_ctx->module);
|
||||||
|
#else
|
||||||
|
for (i = 0; i < comp_ctx->func_ctx_count; i++) {
|
||||||
|
LLVMRunPassManager(common_pass_mgr, comp_ctx->modules[i]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
LLVMDisposePassManager(common_pass_mgr);
|
||||||
|
LLVMPassManagerBuilderDispose(pass_mgr_builder);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Check whether the target supports hardware atomic instructions */
|
/* Check whether the target supports hardware atomic instructions */
|
||||||
static bool
|
static bool
|
||||||
aot_require_lower_atomic_pass(AOTCompContext *comp_ctx)
|
aot_require_lower_atomic_pass(AOTCompContext *comp_ctx)
|
||||||
|
@ -2570,11 +2709,42 @@ aot_require_lower_switch_pass(AOTCompContext *comp_ctx)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
apply_passes_for_indirect_mode(AOTCompContext *comp_ctx)
|
||||||
|
{
|
||||||
|
LLVMPassManagerRef common_pass_mgr;
|
||||||
|
#if WASM_ENABLE_LAZY_JIT != 0
|
||||||
|
uint32 i;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!(common_pass_mgr = LLVMCreatePassManager())) {
|
||||||
|
aot_set_last_error("create pass manager failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
aot_add_expand_memory_op_pass(common_pass_mgr);
|
||||||
|
|
||||||
|
if (aot_require_lower_atomic_pass(comp_ctx))
|
||||||
|
LLVMAddLowerAtomicPass(common_pass_mgr);
|
||||||
|
|
||||||
|
if (aot_require_lower_switch_pass(comp_ctx))
|
||||||
|
LLVMAddLowerSwitchPass(common_pass_mgr);
|
||||||
|
|
||||||
|
#if WASM_ENABLE_LAZY_JIT == 0
|
||||||
|
LLVMRunPassManager(common_pass_mgr, comp_ctx->module);
|
||||||
|
#else
|
||||||
|
for (i = 0; i < comp_ctx->func_ctx_count; i++) {
|
||||||
|
LLVMRunPassManager(common_pass_mgr, comp_ctx->modules[i]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
LLVMDisposePassManager(common_pass_mgr);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
aot_compile_wasm(AOTCompContext *comp_ctx)
|
aot_compile_wasm(AOTCompContext *comp_ctx)
|
||||||
{
|
{
|
||||||
char *msg = NULL;
|
|
||||||
bool ret;
|
|
||||||
uint32 i;
|
uint32 i;
|
||||||
#if WASM_ENABLE_LAZY_JIT != 0
|
#if WASM_ENABLE_LAZY_JIT != 0
|
||||||
LLVMErrorRef err;
|
LLVMErrorRef err;
|
||||||
|
@ -2587,142 +2757,60 @@ aot_compile_wasm(AOTCompContext *comp_ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
bh_print_time("Begin to compile WASM bytecode to LLVM IR");
|
bh_print_time("Begin to compile WASM bytecode to LLVM IR");
|
||||||
|
for (i = 0; i < comp_ctx->func_ctx_count; i++) {
|
||||||
for (i = 0; i < comp_ctx->func_ctx_count; i++)
|
|
||||||
if (!aot_compile_func(comp_ctx, i)) {
|
if (!aot_compile_func(comp_ctx, i)) {
|
||||||
#if 0
|
|
||||||
LLVMDumpModule(comp_ctx->module);
|
|
||||||
char *err;
|
|
||||||
LLVMTargetMachineEmitToFile(comp_ctx->target_machine,
|
|
||||||
comp_ctx->module, "./test.o",
|
|
||||||
LLVMObjectFile, &err);
|
|
||||||
#endif
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#if 0
|
|
||||||
LLVMDumpModule(comp_ctx->module);
|
|
||||||
/* Clear error no, LLVMDumpModule may set errno */
|
|
||||||
errno = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if WASM_ENABLE_DEBUG_AOT != 0
|
#if WASM_ENABLE_DEBUG_AOT != 0
|
||||||
LLVMDIBuilderFinalize(comp_ctx->debug_builder);
|
LLVMDIBuilderFinalize(comp_ctx->debug_builder);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bh_print_time("Begin to verify LLVM module");
|
bh_print_time("Begin to verify LLVM module");
|
||||||
|
if (!veriy_module(comp_ctx)) {
|
||||||
#if WASM_ENABLE_LAZY_JIT == 0
|
return false;
|
||||||
ret = LLVMVerifyModule(comp_ctx->module, LLVMPrintMessageAction, &msg);
|
|
||||||
if (!ret && msg) {
|
|
||||||
if (msg[0] != '\0') {
|
|
||||||
aot_set_last_error(msg);
|
|
||||||
LLVMDisposeMessage(msg);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
LLVMDisposeMessage(msg);
|
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
for (i = 0; i < comp_ctx->func_ctx_count; i++) {
|
if (comp_ctx->optimize) {
|
||||||
ret = LLVMVerifyModule(comp_ctx->modules[i], LLVMPrintMessageAction,
|
if (comp_ctx->is_jit_mode) {
|
||||||
&msg);
|
/* Only run func passes for JIT mode */
|
||||||
if (!ret && msg) {
|
bh_print_time("Begin to run func optimization passes");
|
||||||
if (msg[0] != '\0') {
|
if (!apply_func_passes(comp_ctx)) {
|
||||||
aot_set_last_error(msg);
|
|
||||||
LLVMDisposeMessage(msg);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
LLVMDisposeMessage(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bh_print_time("Begin to run function optimization passes");
|
|
||||||
|
|
||||||
/* Run function pass manager */
|
|
||||||
if (comp_ctx->optimize) {
|
|
||||||
#if WASM_ENABLE_LAZY_JIT == 0
|
|
||||||
LLVMInitializeFunctionPassManager(comp_ctx->pass_mgr);
|
|
||||||
for (i = 0; i < comp_ctx->func_ctx_count; i++) {
|
|
||||||
LLVMRunFunctionPassManager(comp_ctx->pass_mgr,
|
|
||||||
comp_ctx->func_ctxes[i]->func);
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
#if WASM_ENABLE_LLVM_LEGACY_PM == 0
|
||||||
|
/* Run llvm new pass manager for AOT compiler if llvm
|
||||||
|
legacy pass manager isn't used */
|
||||||
|
bh_print_time("Begin to run llvm optimization passes");
|
||||||
|
aot_apply_llvm_new_pass_manager(comp_ctx);
|
||||||
#else
|
#else
|
||||||
for (i = 0; i < comp_ctx->func_ctx_count; i++) {
|
/* Run func passes and lto passes for AOT compiler if llvm
|
||||||
LLVMRunPassManager(comp_ctx->pass_mgr, comp_ctx->modules[i]);
|
legacy pass manager is used */
|
||||||
}
|
bh_print_time("Begin to run func optimization passes");
|
||||||
#endif /* end of WASM_ENABLE_LAZY_JIT */
|
if (!apply_func_passes(comp_ctx)) {
|
||||||
}
|
return false;
|
||||||
|
}
|
||||||
#if WASM_ENABLE_LAZY_JIT == 0
|
if (!comp_ctx->disable_llvm_lto) {
|
||||||
/* Run common pass manager */
|
bh_print_time("Begin to run lto optimization passes");
|
||||||
if (comp_ctx->optimize && !comp_ctx->is_jit_mode
|
if (!apply_lto_passes(comp_ctx)) {
|
||||||
&& !comp_ctx->disable_llvm_lto) {
|
return false;
|
||||||
LLVMPassManagerRef common_pass_mgr = NULL;
|
}
|
||||||
LLVMPassManagerBuilderRef pass_mgr_builder = NULL;
|
}
|
||||||
|
|
||||||
if (!(common_pass_mgr = LLVMCreatePassManager())) {
|
|
||||||
aot_set_last_error("create pass manager failed");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(pass_mgr_builder = LLVMPassManagerBuilderCreate())) {
|
|
||||||
aot_set_last_error("create pass manager builder failed");
|
|
||||||
LLVMDisposePassManager(common_pass_mgr);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
LLVMPassManagerBuilderSetOptLevel(pass_mgr_builder,
|
|
||||||
comp_ctx->opt_level);
|
|
||||||
LLVMPassManagerBuilderPopulateModulePassManager(pass_mgr_builder,
|
|
||||||
common_pass_mgr);
|
|
||||||
LLVMPassManagerBuilderPopulateLTOPassManager(
|
|
||||||
pass_mgr_builder, common_pass_mgr, true, true);
|
|
||||||
|
|
||||||
LLVMRunPassManager(common_pass_mgr, comp_ctx->module);
|
|
||||||
|
|
||||||
LLVMDisposePassManager(common_pass_mgr);
|
|
||||||
LLVMPassManagerBuilderDispose(pass_mgr_builder);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
/* Run passes for AOT indirect mode */
|
||||||
if (comp_ctx->optimize && comp_ctx->is_indirect_mode) {
|
if (comp_ctx->is_indirect_mode) {
|
||||||
LLVMPassManagerRef common_pass_mgr = NULL;
|
bh_print_time("Begin to run optimization passes "
|
||||||
|
"for indirect mode");
|
||||||
if (!(common_pass_mgr = LLVMCreatePassManager())) {
|
if (!apply_passes_for_indirect_mode(comp_ctx)) {
|
||||||
aot_set_last_error("create pass manager failed");
|
return false;
|
||||||
return false;
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
aot_add_expand_memory_op_pass(common_pass_mgr);
|
|
||||||
|
|
||||||
if (aot_require_lower_atomic_pass(comp_ctx))
|
|
||||||
LLVMAddLowerAtomicPass(common_pass_mgr);
|
|
||||||
|
|
||||||
if (aot_require_lower_switch_pass(comp_ctx))
|
|
||||||
LLVMAddLowerSwitchPass(common_pass_mgr);
|
|
||||||
|
|
||||||
#if WASM_ENABLE_LAZY_JIT == 0
|
|
||||||
LLVMRunPassManager(common_pass_mgr, comp_ctx->module);
|
|
||||||
#else
|
|
||||||
for (i = 0; i < comp_ctx->func_ctx_count; i++)
|
|
||||||
LLVMRunPassManager(common_pass_mgr, comp_ctx->modules[i]);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
LLVMDisposePassManager(common_pass_mgr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
#if WASM_ENABLE_LAZY_JIT == 0
|
|
||||||
LLVMDumpModule(comp_ctx->module);
|
|
||||||
#else
|
|
||||||
for (i = 0; i < comp_ctx->func_ctx_count; i++) {
|
|
||||||
LLVMDumpModule(comp_ctx->modules[i]);
|
|
||||||
os_printf("\n");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if WASM_ENABLE_LAZY_JIT != 0
|
#if WASM_ENABLE_LAZY_JIT != 0
|
||||||
orc_main_dylib = LLVMOrcLLJITGetMainJITDylib(comp_ctx->orc_lazyjit);
|
orc_main_dylib = LLVMOrcLLJITGetMainJITDylib(comp_ctx->orc_lazyjit);
|
||||||
if (!orc_main_dylib) {
|
if (!orc_main_dylib) {
|
||||||
|
@ -2750,6 +2838,16 @@ aot_compile_wasm(AOTCompContext *comp_ctx)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
#if WASM_ENABLE_LAZY_JIT == 0
|
||||||
|
LLVMDumpModule(comp_ctx->module);
|
||||||
|
#else
|
||||||
|
for (i = 0; i < comp_ctx->func_ctx_count; i++) {
|
||||||
|
LLVMDumpModule(comp_ctx->modules[i]);
|
||||||
|
os_printf("\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2800,205 +2898,4 @@ aot_emit_object_file(AOTCompContext *comp_ctx, char *file_name)
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct AOTFileMap {
|
|
||||||
uint8 *wasm_file_buf;
|
|
||||||
uint32 wasm_file_size;
|
|
||||||
uint8 *aot_file_buf;
|
|
||||||
uint32 aot_file_size;
|
|
||||||
struct AOTFileMap *next;
|
|
||||||
} AOTFileMap;
|
|
||||||
|
|
||||||
static bool aot_compile_wasm_file_inited = false;
|
|
||||||
static AOTFileMap *aot_file_maps = NULL;
|
|
||||||
static korp_mutex aot_file_map_lock;
|
|
||||||
|
|
||||||
bool
|
|
||||||
aot_compile_wasm_file_init()
|
|
||||||
{
|
|
||||||
if (aot_compile_wasm_file_inited) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (BHT_OK != os_mutex_init(&aot_file_map_lock)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
aot_file_maps = NULL;
|
|
||||||
aot_compile_wasm_file_inited = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
aot_compile_wasm_file_destroy()
|
|
||||||
{
|
|
||||||
AOTFileMap *file_map = aot_file_maps, *file_map_next;
|
|
||||||
|
|
||||||
if (!aot_compile_wasm_file_inited) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (file_map) {
|
|
||||||
file_map_next = file_map->next;
|
|
||||||
|
|
||||||
wasm_runtime_free(file_map->wasm_file_buf);
|
|
||||||
wasm_runtime_free(file_map->aot_file_buf);
|
|
||||||
wasm_runtime_free(file_map);
|
|
||||||
|
|
||||||
file_map = file_map_next;
|
|
||||||
}
|
|
||||||
|
|
||||||
aot_file_maps = NULL;
|
|
||||||
os_mutex_destroy(&aot_file_map_lock);
|
|
||||||
aot_compile_wasm_file_inited = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
set_error_buf(char *error_buf, uint32 error_buf_size, const char *string)
|
|
||||||
{
|
|
||||||
if (error_buf != NULL) {
|
|
||||||
snprintf(error_buf, error_buf_size, "WASM module load failed: %s",
|
|
||||||
string);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8 *
|
|
||||||
aot_compile_wasm_file(const uint8 *wasm_file_buf, uint32 wasm_file_size,
|
|
||||||
uint32 opt_level, uint32 size_level, char *error_buf,
|
|
||||||
uint32 error_buf_size, uint32 *p_aot_file_size)
|
|
||||||
{
|
|
||||||
WASMModule *wasm_module = NULL;
|
|
||||||
AOTCompData *comp_data = NULL;
|
|
||||||
AOTCompContext *comp_ctx = NULL;
|
|
||||||
RuntimeInitArgs init_args;
|
|
||||||
AOTCompOption option = { 0 };
|
|
||||||
AOTFileMap *file_map = NULL, *file_map_next;
|
|
||||||
uint8 *wasm_file_buf_cloned = NULL;
|
|
||||||
uint8 *aot_file_buf = NULL;
|
|
||||||
uint32 aot_file_size;
|
|
||||||
|
|
||||||
option.is_jit_mode = false;
|
|
||||||
option.opt_level = opt_level;
|
|
||||||
option.size_level = size_level;
|
|
||||||
option.output_format = AOT_FORMAT_FILE;
|
|
||||||
/* default value, enable or disable depends on the platform */
|
|
||||||
option.bounds_checks = 2;
|
|
||||||
option.enable_aux_stack_check = true;
|
|
||||||
#if WASM_ENABLE_BULK_MEMORY != 0
|
|
||||||
option.enable_bulk_memory = true;
|
|
||||||
#endif
|
|
||||||
#if WASM_ENABLE_THREAD_MGR != 0
|
|
||||||
option.enable_thread_mgr = true;
|
|
||||||
#endif
|
|
||||||
#if WASM_ENABLE_TAIL_CALL != 0
|
|
||||||
option.enable_tail_call = true;
|
|
||||||
#endif
|
|
||||||
#if WASM_ENABLE_SIMD != 0
|
|
||||||
option.enable_simd = true;
|
|
||||||
#endif
|
|
||||||
#if WASM_ENABLE_REF_TYPES != 0
|
|
||||||
option.enable_ref_types = true;
|
|
||||||
#endif
|
|
||||||
#if (WASM_ENABLE_PERF_PROFILING != 0) || (WASM_ENABLE_DUMP_CALL_STACK != 0)
|
|
||||||
option.enable_aux_stack_frame = true;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
memset(&init_args, 0, sizeof(RuntimeInitArgs));
|
|
||||||
|
|
||||||
init_args.mem_alloc_type = Alloc_With_Allocator;
|
|
||||||
init_args.mem_alloc_option.allocator.malloc_func = malloc;
|
|
||||||
init_args.mem_alloc_option.allocator.realloc_func = realloc;
|
|
||||||
init_args.mem_alloc_option.allocator.free_func = free;
|
|
||||||
|
|
||||||
os_mutex_lock(&aot_file_map_lock);
|
|
||||||
|
|
||||||
/* lookup the file maps */
|
|
||||||
file_map = aot_file_maps;
|
|
||||||
while (file_map) {
|
|
||||||
file_map_next = file_map->next;
|
|
||||||
|
|
||||||
if (wasm_file_size == file_map->wasm_file_size
|
|
||||||
&& memcmp(wasm_file_buf, file_map->wasm_file_buf, wasm_file_size)
|
|
||||||
== 0) {
|
|
||||||
os_mutex_unlock(&aot_file_map_lock);
|
|
||||||
/* found */
|
|
||||||
*p_aot_file_size = file_map->aot_file_size;
|
|
||||||
return file_map->aot_file_buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
file_map = file_map_next;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* not found, initialize file map and clone wasm file */
|
|
||||||
if (!(file_map = wasm_runtime_malloc(sizeof(AOTFileMap)))
|
|
||||||
|| !(wasm_file_buf_cloned = wasm_runtime_malloc(wasm_file_size))) {
|
|
||||||
set_error_buf(error_buf, error_buf_size, "allocate memory failed");
|
|
||||||
goto fail1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bh_memcpy_s(wasm_file_buf_cloned, wasm_file_size, wasm_file_buf,
|
|
||||||
wasm_file_size);
|
|
||||||
memset(file_map, 0, sizeof(AOTFileMap));
|
|
||||||
file_map->wasm_file_buf = wasm_file_buf_cloned;
|
|
||||||
file_map->wasm_file_size = wasm_file_size;
|
|
||||||
|
|
||||||
/* load WASM module */
|
|
||||||
if (!(wasm_module = wasm_load(wasm_file_buf, wasm_file_size, error_buf,
|
|
||||||
sizeof(error_buf)))) {
|
|
||||||
goto fail1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(comp_data = aot_create_comp_data(wasm_module))) {
|
|
||||||
set_error_buf(error_buf, error_buf_size, aot_get_last_error());
|
|
||||||
goto fail2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(comp_ctx = aot_create_comp_context(comp_data, &option))) {
|
|
||||||
set_error_buf(error_buf, error_buf_size, aot_get_last_error());
|
|
||||||
goto fail3;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!aot_compile_wasm(comp_ctx)) {
|
|
||||||
set_error_buf(error_buf, error_buf_size, aot_get_last_error());
|
|
||||||
goto fail4;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(aot_file_buf =
|
|
||||||
aot_emit_aot_file_buf(comp_ctx, comp_data, &aot_file_size))) {
|
|
||||||
set_error_buf(error_buf, error_buf_size, aot_get_last_error());
|
|
||||||
goto fail4;
|
|
||||||
}
|
|
||||||
|
|
||||||
file_map->aot_file_buf = aot_file_buf;
|
|
||||||
file_map->aot_file_size = aot_file_size;
|
|
||||||
|
|
||||||
if (!aot_file_maps)
|
|
||||||
aot_file_maps = file_map;
|
|
||||||
else {
|
|
||||||
file_map->next = aot_file_maps;
|
|
||||||
aot_file_maps = file_map;
|
|
||||||
}
|
|
||||||
|
|
||||||
*p_aot_file_size = aot_file_size;
|
|
||||||
|
|
||||||
fail4:
|
|
||||||
/* Destroy compiler context */
|
|
||||||
aot_destroy_comp_context(comp_ctx);
|
|
||||||
fail3:
|
|
||||||
/* Destroy compile data */
|
|
||||||
aot_destroy_comp_data(comp_data);
|
|
||||||
fail2:
|
|
||||||
wasm_unload(wasm_module);
|
|
||||||
fail1:
|
|
||||||
if (!aot_file_buf) {
|
|
||||||
if (wasm_file_buf_cloned)
|
|
||||||
wasm_runtime_free(wasm_file_buf_cloned);
|
|
||||||
if (file_map)
|
|
||||||
wasm_runtime_free(file_map);
|
|
||||||
}
|
|
||||||
|
|
||||||
os_mutex_unlock(&aot_file_map_lock);
|
|
||||||
|
|
||||||
return aot_file_buf;
|
|
||||||
}
|
|
||||||
#endif /* end of WASM_ENABLE_LAZY_JIT == 0 */
|
#endif /* end of WASM_ENABLE_LAZY_JIT == 0 */
|
||||||
|
|
|
@ -2806,5 +2806,4 @@ fail1:
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
#endif /* end of WASM_ENABLE_LAZY_JIT == 0 */
|
||||||
#endif /* end of WASM_ENABLE_JIT */
|
|
||||||
|
|
|
@ -2024,48 +2024,6 @@ aot_create_comp_context(AOTCompData *comp_data, aot_comp_option_t option)
|
||||||
if (option->output_format == AOT_LLVMIR_UNOPT_FILE)
|
if (option->output_format == AOT_LLVMIR_UNOPT_FILE)
|
||||||
comp_ctx->optimize = false;
|
comp_ctx->optimize = false;
|
||||||
|
|
||||||
#if WASM_ENABLE_LAZY_JIT == 0
|
|
||||||
if (!(comp_ctx->pass_mgr =
|
|
||||||
LLVMCreateFunctionPassManagerForModule(comp_ctx->module))) {
|
|
||||||
aot_set_last_error("create LLVM pass manager failed.");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (!(comp_ctx->pass_mgr = LLVMCreatePassManager())) {
|
|
||||||
aot_set_last_error("create LLVM pass manager failed.");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
LLVMAddPromoteMemoryToRegisterPass(comp_ctx->pass_mgr);
|
|
||||||
LLVMAddInstructionCombiningPass(comp_ctx->pass_mgr);
|
|
||||||
LLVMAddCFGSimplificationPass(comp_ctx->pass_mgr);
|
|
||||||
LLVMAddJumpThreadingPass(comp_ctx->pass_mgr);
|
|
||||||
#if LLVM_VERSION_MAJOR < 12
|
|
||||||
LLVMAddConstantPropagationPass(comp_ctx->pass_mgr);
|
|
||||||
#endif
|
|
||||||
LLVMAddIndVarSimplifyPass(comp_ctx->pass_mgr);
|
|
||||||
|
|
||||||
if (!option->is_jit_mode) {
|
|
||||||
/* Put Vectorize passes before GVN/LICM passes as the former
|
|
||||||
might gain more performance improvement and the latter might
|
|
||||||
break the optimizations for the former */
|
|
||||||
LLVMAddLoopVectorizePass(comp_ctx->pass_mgr);
|
|
||||||
LLVMAddSLPVectorizePass(comp_ctx->pass_mgr);
|
|
||||||
LLVMAddLoopRotatePass(comp_ctx->pass_mgr);
|
|
||||||
LLVMAddLoopUnswitchPass(comp_ctx->pass_mgr);
|
|
||||||
LLVMAddInstructionCombiningPass(comp_ctx->pass_mgr);
|
|
||||||
LLVMAddCFGSimplificationPass(comp_ctx->pass_mgr);
|
|
||||||
if (!option->enable_thread_mgr) {
|
|
||||||
/* These two passes may destroy the volatile semantics,
|
|
||||||
disable them when building as multi-thread mode */
|
|
||||||
LLVMAddGVNPass(comp_ctx->pass_mgr);
|
|
||||||
LLVMAddLICMPass(comp_ctx->pass_mgr);
|
|
||||||
LLVMAddInstructionCombiningPass(comp_ctx->pass_mgr);
|
|
||||||
LLVMAddCFGSimplificationPass(comp_ctx->pass_mgr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create metadata for llvm float experimental constrained intrinsics */
|
/* Create metadata for llvm float experimental constrained intrinsics */
|
||||||
if (!(comp_ctx->fp_rounding_mode = LLVMMDStringInContext(
|
if (!(comp_ctx->fp_rounding_mode = LLVMMDStringInContext(
|
||||||
comp_ctx->context, fp_round, (uint32)strlen(fp_round)))
|
comp_ctx->context, fp_round, (uint32)strlen(fp_round)))
|
||||||
|
@ -2132,13 +2090,6 @@ aot_destroy_comp_context(AOTCompContext *comp_ctx)
|
||||||
if (!comp_ctx)
|
if (!comp_ctx)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (comp_ctx->pass_mgr) {
|
|
||||||
#if WASM_ENABLE_LAZY_JIT == 0
|
|
||||||
LLVMFinalizeFunctionPassManager(comp_ctx->pass_mgr);
|
|
||||||
#endif
|
|
||||||
LLVMDisposePassManager(comp_ctx->pass_mgr);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if WASM_ENABLE_LAZY_JIT != 0
|
#if WASM_ENABLE_LAZY_JIT != 0
|
||||||
if (comp_ctx->orc_symbol_map_pairs)
|
if (comp_ctx->orc_symbol_map_pairs)
|
||||||
wasm_runtime_free(comp_ctx->orc_symbol_map_pairs);
|
wasm_runtime_free(comp_ctx->orc_symbol_map_pairs);
|
||||||
|
|
|
@ -331,9 +331,6 @@ typedef struct AOTCompContext {
|
||||||
uint32 opt_level;
|
uint32 opt_level;
|
||||||
uint32 size_level;
|
uint32 size_level;
|
||||||
|
|
||||||
/* LLVM pass manager to optimize the JITed code */
|
|
||||||
LLVMPassManagerRef pass_mgr;
|
|
||||||
|
|
||||||
/* LLVM floating-point rounding mode metadata */
|
/* LLVM floating-point rounding mode metadata */
|
||||||
LLVMValueRef fp_rounding_mode;
|
LLVMValueRef fp_rounding_mode;
|
||||||
|
|
||||||
|
@ -469,6 +466,9 @@ aot_check_simd_compatibility(const char *arch_c_str, const char *cpu_c_str);
|
||||||
void
|
void
|
||||||
aot_add_expand_memory_op_pass(LLVMPassManagerRef pass);
|
aot_add_expand_memory_op_pass(LLVMPassManagerRef pass);
|
||||||
|
|
||||||
|
void
|
||||||
|
aot_apply_llvm_new_pass_manager(AOTCompContext *comp_ctx);
|
||||||
|
|
||||||
#if WASM_ENABLE_LAZY_JIT != 0
|
#if WASM_ENABLE_LAZY_JIT != 0
|
||||||
LLVMOrcJITTargetMachineBuilderRef
|
LLVMOrcJITTargetMachineBuilderRef
|
||||||
LLVMOrcJITTargetMachineBuilderCreateFromTargetMachine(LLVMTargetMachineRef TM);
|
LLVMOrcJITTargetMachineBuilderCreateFromTargetMachine(LLVMTargetMachineRef TM);
|
||||||
|
|
|
@ -30,29 +30,55 @@
|
||||||
#include <llvm/Target/TargetMachine.h>
|
#include <llvm/Target/TargetMachine.h>
|
||||||
#include <llvm/Target/TargetOptions.h>
|
#include <llvm/Target/TargetOptions.h>
|
||||||
#include <llvm/Transforms/Utils/LowerMemIntrinsics.h>
|
#include <llvm/Transforms/Utils/LowerMemIntrinsics.h>
|
||||||
|
#include <llvm/Transforms/Vectorize/LoopVectorize.h>
|
||||||
|
#include <llvm/Transforms/Vectorize/LoadStoreVectorizer.h>
|
||||||
|
#include <llvm/Transforms/Vectorize/SLPVectorizer.h>
|
||||||
|
#include <llvm/Transforms/Scalar/LoopRotation.h>
|
||||||
|
#include <llvm/Transforms/Scalar/SimpleLoopUnswitch.h>
|
||||||
|
#include <llvm/Transforms/Scalar/LICM.h>
|
||||||
|
#include <llvm/Transforms/Scalar/GVN.h>
|
||||||
|
#include <llvm/Passes/PassBuilder.h>
|
||||||
|
#include <llvm/Analysis/TargetLibraryInfo.h>
|
||||||
|
#if LLVM_VERSION_MAJOR >= 12
|
||||||
|
#include <llvm/Analysis/AliasAnalysis.h>
|
||||||
|
#endif
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#if WASM_ENABLE_LAZY_JIT != 0
|
#if WASM_ENABLE_LAZY_JIT != 0
|
||||||
#include "../aot/aot_runtime.h"
|
#include "../aot/aot_runtime.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "aot_llvm.h"
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
using namespace llvm::orc;
|
using namespace llvm::orc;
|
||||||
|
|
||||||
extern "C" LLVMBool
|
extern "C" {
|
||||||
|
|
||||||
|
LLVMBool
|
||||||
WAMRCreateMCJITCompilerForModule(LLVMExecutionEngineRef *OutJIT,
|
WAMRCreateMCJITCompilerForModule(LLVMExecutionEngineRef *OutJIT,
|
||||||
LLVMModuleRef M,
|
LLVMModuleRef M,
|
||||||
LLVMMCJITCompilerOptions *PassedOptions,
|
LLVMMCJITCompilerOptions *PassedOptions,
|
||||||
size_t SizeOfPassedOptions, char **OutError);
|
size_t SizeOfPassedOptions, char **OutError);
|
||||||
|
|
||||||
extern "C" bool
|
bool
|
||||||
aot_check_simd_compatibility(const char *arch_c_str, const char *cpu_c_str);
|
aot_check_simd_compatibility(const char *arch_c_str, const char *cpu_c_str);
|
||||||
|
|
||||||
extern "C" void
|
void
|
||||||
aot_add_expand_memory_op_pass(LLVMPassManagerRef pass);
|
aot_add_expand_memory_op_pass(LLVMPassManagerRef pass);
|
||||||
|
|
||||||
extern "C" void
|
void
|
||||||
aot_func_disable_tce(LLVMValueRef func);
|
aot_func_disable_tce(LLVMValueRef func);
|
||||||
|
|
||||||
|
void
|
||||||
|
aot_apply_llvm_new_pass_manager(AOTCompContext *comp_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TargetMachine *
|
||||||
|
unwrap(LLVMTargetMachineRef P)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<TargetMachine *>(P);
|
||||||
|
}
|
||||||
|
|
||||||
LLVMBool
|
LLVMBool
|
||||||
WAMRCreateMCJITCompilerForModule(LLVMExecutionEngineRef *OutJIT,
|
WAMRCreateMCJITCompilerForModule(LLVMExecutionEngineRef *OutJIT,
|
||||||
LLVMModuleRef M,
|
LLVMModuleRef M,
|
||||||
|
@ -334,3 +360,121 @@ aot_func_disable_tce(LLVMValueRef func)
|
||||||
"disable-tail-calls", "true");
|
"disable-tail-calls", "true");
|
||||||
F->setAttributes(Attrs);
|
F->setAttributes(Attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
aot_apply_llvm_new_pass_manager(AOTCompContext *comp_ctx)
|
||||||
|
{
|
||||||
|
Module *M;
|
||||||
|
TargetMachine *TM = unwrap(comp_ctx->target_machine);
|
||||||
|
bool disable_llvm_lto = false;
|
||||||
|
|
||||||
|
LoopAnalysisManager LAM;
|
||||||
|
FunctionAnalysisManager FAM;
|
||||||
|
CGSCCAnalysisManager CGAM;
|
||||||
|
ModuleAnalysisManager MAM;
|
||||||
|
|
||||||
|
PipelineTuningOptions PTO;
|
||||||
|
PTO.LoopVectorization = true;
|
||||||
|
PTO.SLPVectorization = true;
|
||||||
|
PTO.LoopUnrolling = true;
|
||||||
|
|
||||||
|
#if LLVM_VERSION_MAJOR == 12
|
||||||
|
PassBuilder PB(false, TM, PTO);
|
||||||
|
#else
|
||||||
|
PassBuilder PB(TM, PTO);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Register the target library analysis directly and give it a
|
||||||
|
// customized preset TLI.
|
||||||
|
std::unique_ptr<TargetLibraryInfoImpl> TLII(
|
||||||
|
new TargetLibraryInfoImpl(Triple(TM->getTargetTriple())));
|
||||||
|
FAM.registerPass([&] { return TargetLibraryAnalysis(*TLII); });
|
||||||
|
|
||||||
|
// Register the AA manager first so that our version is the one used.
|
||||||
|
AAManager AA = PB.buildDefaultAAPipeline();
|
||||||
|
FAM.registerPass([&] { return std::move(AA); });
|
||||||
|
|
||||||
|
// Register all the basic analyses with the managers.
|
||||||
|
PB.registerModuleAnalyses(MAM);
|
||||||
|
PB.registerCGSCCAnalyses(CGAM);
|
||||||
|
PB.registerFunctionAnalyses(FAM);
|
||||||
|
PB.registerLoopAnalyses(LAM);
|
||||||
|
PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
|
||||||
|
|
||||||
|
ModulePassManager MPM;
|
||||||
|
|
||||||
|
PassBuilder::OptimizationLevel OL;
|
||||||
|
|
||||||
|
switch (comp_ctx->opt_level) {
|
||||||
|
case 0:
|
||||||
|
OL = PassBuilder::OptimizationLevel::O0;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
OL = PassBuilder::OptimizationLevel::O1;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
OL = PassBuilder::OptimizationLevel::O2;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
default:
|
||||||
|
OL = PassBuilder::OptimizationLevel::O3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (comp_ctx->disable_llvm_lto) {
|
||||||
|
disable_llvm_lto = true;
|
||||||
|
}
|
||||||
|
#if WASM_ENABLE_SPEC_TEST != 0
|
||||||
|
disable_llvm_lto = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (disable_llvm_lto) {
|
||||||
|
uint32 i;
|
||||||
|
|
||||||
|
for (i = 0; i < comp_ctx->func_ctx_count; i++) {
|
||||||
|
aot_func_disable_tce(comp_ctx->func_ctxes[i]->func);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (comp_ctx->is_jit_mode) {
|
||||||
|
/* Apply normal pipeline for JIT mode, without
|
||||||
|
Vectorize related passes, without LTO */
|
||||||
|
MPM.addPass(PB.buildPerModuleDefaultPipeline(OL));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
FunctionPassManager FPM;
|
||||||
|
|
||||||
|
/* Apply Vectorize related passes for AOT mode */
|
||||||
|
FPM.addPass(LoopVectorizePass());
|
||||||
|
FPM.addPass(SLPVectorizerPass());
|
||||||
|
FPM.addPass(LoadStoreVectorizerPass());
|
||||||
|
|
||||||
|
/*
|
||||||
|
FPM.addPass(createFunctionToLoopPassAdaptor(LICMPass()));
|
||||||
|
FPM.addPass(createFunctionToLoopPassAdaptor(LoopRotatePass()));
|
||||||
|
FPM.addPass(createFunctionToLoopPassAdaptor(SimpleLoopUnswitchPass()));
|
||||||
|
*/
|
||||||
|
|
||||||
|
MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
|
||||||
|
|
||||||
|
if (!disable_llvm_lto) {
|
||||||
|
/* Apply LTO for AOT mode */
|
||||||
|
MPM.addPass(PB.buildLTODefaultPipeline(OL, NULL));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
MPM.addPass(PB.buildPerModuleDefaultPipeline(OL));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if WASM_ENABLE_LAZY_JIT == 0
|
||||||
|
M = unwrap(comp_ctx->module);
|
||||||
|
MPM.run(*M, MAM);
|
||||||
|
#else
|
||||||
|
uint32 i;
|
||||||
|
|
||||||
|
for (i = 0; i < comp_ctx->func_ctx_count; i++) {
|
||||||
|
M = unwrap(comp_ctx->modules[i]);
|
||||||
|
MPM.run(*M, MAM);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
|
@ -83,17 +83,6 @@ aot_emit_aot_file(aot_comp_context_t comp_ctx, aot_comp_data_t comp_data,
|
||||||
void
|
void
|
||||||
aot_destroy_aot_file(uint8_t *aot_file);
|
aot_destroy_aot_file(uint8_t *aot_file);
|
||||||
|
|
||||||
bool
|
|
||||||
aot_compile_wasm_file_init();
|
|
||||||
|
|
||||||
uint8_t *
|
|
||||||
aot_compile_wasm_file(const uint8_t *wasm_file_buf, uint32_t wasm_file_size,
|
|
||||||
uint32_t opt_level, uint32_t size_level, char *error_buf,
|
|
||||||
uint32_t error_buf_size, uint32_t *p_aot_file_size);
|
|
||||||
|
|
||||||
void
|
|
||||||
aot_compile_wasm_file_destroy();
|
|
||||||
|
|
||||||
char *
|
char *
|
||||||
aot_get_last_error();
|
aot_get_last_error();
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,10 @@ add_definitions(-DWASM_ENABLE_CUSTOM_NAME_SECTION=1)
|
||||||
add_definitions(-DWASM_ENABLE_DUMP_CALL_STACK=1)
|
add_definitions(-DWASM_ENABLE_DUMP_CALL_STACK=1)
|
||||||
add_definitions(-DWASM_ENABLE_PERF_PROFILING=1)
|
add_definitions(-DWASM_ENABLE_PERF_PROFILING=1)
|
||||||
|
|
||||||
|
if (WAMR_BUILD_LLVM_LEGACY_PM EQUAL 1)
|
||||||
|
add_definitions(-DWASM_ENABLE_LLVM_LEGACY_PM=1)
|
||||||
|
endif()
|
||||||
|
|
||||||
# Set WAMR_BUILD_TARGET, currently values supported:
|
# Set WAMR_BUILD_TARGET, currently values supported:
|
||||||
# "X86_64", "AMD_64", "X86_32", "ARM_32", "MIPS_32", "XTENSA_32"
|
# "X86_64", "AMD_64", "X86_32", "ARM_32", "MIPS_32", "XTENSA_32"
|
||||||
if (NOT WAMR_BUILD_TARGET)
|
if (NOT WAMR_BUILD_TARGET)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user