diff --git a/build-scripts/config_common.cmake b/build-scripts/config_common.cmake index ba44ceee6a..19d12b6a43 100644 --- a/build-scripts/config_common.cmake +++ b/build-scripts/config_common.cmake @@ -131,9 +131,9 @@ else () endif () if (WAMR_BUILD_JIT EQUAL 1) if (WAMR_BUILD_LAZY_JIT EQUAL 1) - message (" WAMR Lazy JIT enabled") + message (" WAMR LLVM Orc Lazy JIT enabled") else () - message (" WAMR MC JIT enabled") + message (" WAMR LLVM MC JIT enabled") endif () else () message (" WAMR JIT disabled") diff --git a/core/config.h b/core/config.h index 065af251b2..cd3a0eef2d 100644 --- a/core/config.h +++ b/core/config.h @@ -98,6 +98,14 @@ #define WASM_ENABLE_WAMR_COMPILER 0 #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 #define WASM_ENABLE_LIBC_BUILTIN 0 #endif diff --git a/core/iwasm/common/wasm_c_api.c b/core/iwasm/common/wasm_c_api.c index a77f43c8d6..660cdaf05c 100644 --- a/core/iwasm/common/wasm_c_api.c +++ b/core/iwasm/common/wasm_c_api.c @@ -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(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 */ own wasm_config_t * wasm_config_new(void) @@ -266,10 +252,6 @@ wasm_engine_delete_internal(wasm_engine_t *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(); } @@ -317,12 +299,6 @@ wasm_engine_new_internal(mem_alloc_type_t type, const MemAllocOption *opts) bh_log_set_verbose_level(3); #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 */ if (!(engine = malloc_internal(sizeof(wasm_engine_t)))) { goto failed; @@ -1820,10 +1796,6 @@ wasm_module_new(wasm_store_t *store, const wasm_byte_vec_t *binary) char error_buf[128] = { 0 }; wasm_module_ex_t *module_ex = NULL; 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); @@ -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); -#if WASM_ENABLE_AOT != 0 && WASM_ENABLE_JIT != 0 && WASM_ENABLE_LAZY_JIT == 0 - if (Wasm_Module_Bytecode == pkg_type) { - if (!(aot_file_buf = aot_compile_wasm_file( - (uint8 *)module_ex->binary->data, - (uint32)module_ex->binary->size, 3, 3, error_buf, - (uint32)sizeof(error_buf), &aot_file_size))) { - 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; - } + 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 */ diff --git a/core/iwasm/compilation/aot_compiler.c b/core/iwasm/compilation/aot_compiler.c index 2807fef2fd..c4dac553a4 100644 --- a/core/iwasm/compilation/aot_compiler.c +++ b/core/iwasm/compilation/aot_compiler.c @@ -2537,6 +2537,145 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index) 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 */ static bool aot_require_lower_atomic_pass(AOTCompContext *comp_ctx) @@ -2570,11 +2709,42 @@ aot_require_lower_switch_pass(AOTCompContext *comp_ctx) 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 aot_compile_wasm(AOTCompContext *comp_ctx) { - char *msg = NULL; - bool ret; uint32 i; #if WASM_ENABLE_LAZY_JIT != 0 LLVMErrorRef err; @@ -2587,142 +2757,60 @@ aot_compile_wasm(AOTCompContext *comp_ctx) } 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 0 - LLVMDumpModule(comp_ctx->module); - char *err; - LLVMTargetMachineEmitToFile(comp_ctx->target_machine, - comp_ctx->module, "./test.o", - LLVMObjectFile, &err); -#endif return false; } - -#if 0 - LLVMDumpModule(comp_ctx->module); - /* Clear error no, LLVMDumpModule may set errno */ - errno = 0; -#endif + } #if WASM_ENABLE_DEBUG_AOT != 0 LLVMDIBuilderFinalize(comp_ctx->debug_builder); #endif bh_print_time("Begin to verify LLVM module"); - -#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 - 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); - } + if (!veriy_module(comp_ctx)) { + return false; } -#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); + if (comp_ctx->is_jit_mode) { + /* Only run func passes for JIT mode */ + bh_print_time("Begin to run func optimization passes"); + if (!apply_func_passes(comp_ctx)) { + return false; + } } + 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 - for (i = 0; i < comp_ctx->func_ctx_count; i++) { - LLVMRunPassManager(comp_ctx->pass_mgr, comp_ctx->modules[i]); - } -#endif /* end of WASM_ENABLE_LAZY_JIT */ - } - -#if WASM_ENABLE_LAZY_JIT == 0 - /* Run common pass manager */ - if (comp_ctx->optimize && !comp_ctx->is_jit_mode - && !comp_ctx->disable_llvm_lto) { - 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); - } + /* Run func passes and lto passes for AOT compiler if llvm + legacy pass manager is used */ + bh_print_time("Begin to run func optimization passes"); + if (!apply_func_passes(comp_ctx)) { + return false; + } + if (!comp_ctx->disable_llvm_lto) { + bh_print_time("Begin to run lto optimization passes"); + if (!apply_lto_passes(comp_ctx)) { + return false; + } + } #endif - - if (comp_ctx->optimize && comp_ctx->is_indirect_mode) { - LLVMPassManagerRef common_pass_mgr = NULL; - - if (!(common_pass_mgr = LLVMCreatePassManager())) { - aot_set_last_error("create pass manager failed"); - return false; + /* Run passes for AOT indirect mode */ + if (comp_ctx->is_indirect_mode) { + bh_print_time("Begin to run optimization passes " + "for indirect mode"); + if (!apply_passes_for_indirect_mode(comp_ctx)) { + 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 orc_main_dylib = LLVMOrcLLJITGetMainJITDylib(comp_ctx->orc_lazyjit); if (!orc_main_dylib) { @@ -2750,6 +2838,16 @@ aot_compile_wasm(AOTCompContext *comp_ctx) } #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; } @@ -2800,205 +2898,4 @@ aot_emit_object_file(AOTCompContext *comp_ctx, char *file_name) 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 */ diff --git a/core/iwasm/compilation/aot_emit_aot_file.c b/core/iwasm/compilation/aot_emit_aot_file.c index d0b1d74a0a..7b98482ec8 100644 --- a/core/iwasm/compilation/aot_emit_aot_file.c +++ b/core/iwasm/compilation/aot_emit_aot_file.c @@ -2806,5 +2806,4 @@ aot_emit_aot_file(AOTCompContext *comp_ctx, AOTCompData *comp_data, return ret; } - -#endif /* end of WASM_ENABLE_JIT */ +#endif /* end of WASM_ENABLE_LAZY_JIT == 0 */ diff --git a/core/iwasm/compilation/aot_llvm.c b/core/iwasm/compilation/aot_llvm.c index c126dcdd4b..f9e03f9c5b 100644 --- a/core/iwasm/compilation/aot_llvm.c +++ b/core/iwasm/compilation/aot_llvm.c @@ -2024,48 +2024,6 @@ aot_create_comp_context(AOTCompData *comp_data, aot_comp_option_t option) if (option->output_format == AOT_LLVMIR_UNOPT_FILE) 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 */ if (!(comp_ctx->fp_rounding_mode = LLVMMDStringInContext( comp_ctx->context, fp_round, (uint32)strlen(fp_round))) @@ -2132,13 +2090,6 @@ aot_destroy_comp_context(AOTCompContext *comp_ctx) if (!comp_ctx) 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 (comp_ctx->orc_symbol_map_pairs) wasm_runtime_free(comp_ctx->orc_symbol_map_pairs); diff --git a/core/iwasm/compilation/aot_llvm.h b/core/iwasm/compilation/aot_llvm.h index 82f4b0dcba..1cb8d3b754 100644 --- a/core/iwasm/compilation/aot_llvm.h +++ b/core/iwasm/compilation/aot_llvm.h @@ -331,9 +331,6 @@ typedef struct AOTCompContext { uint32 opt_level; uint32 size_level; - /* LLVM pass manager to optimize the JITed code */ - LLVMPassManagerRef pass_mgr; - /* LLVM floating-point rounding mode metadata */ LLVMValueRef fp_rounding_mode; @@ -469,6 +466,9 @@ aot_check_simd_compatibility(const char *arch_c_str, const char *cpu_c_str); void aot_add_expand_memory_op_pass(LLVMPassManagerRef pass); +void +aot_apply_llvm_new_pass_manager(AOTCompContext *comp_ctx); + #if WASM_ENABLE_LAZY_JIT != 0 LLVMOrcJITTargetMachineBuilderRef LLVMOrcJITTargetMachineBuilderCreateFromTargetMachine(LLVMTargetMachineRef TM); diff --git a/core/iwasm/compilation/aot_llvm_extra.cpp b/core/iwasm/compilation/aot_llvm_extra.cpp index f3aaf4ec89..45aeb9cdd2 100644 --- a/core/iwasm/compilation/aot_llvm_extra.cpp +++ b/core/iwasm/compilation/aot_llvm_extra.cpp @@ -30,29 +30,55 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if LLVM_VERSION_MAJOR >= 12 +#include +#endif #include #if WASM_ENABLE_LAZY_JIT != 0 #include "../aot/aot_runtime.h" #endif +#include "aot_llvm.h" + using namespace llvm; using namespace llvm::orc; -extern "C" LLVMBool +extern "C" { + +LLVMBool WAMRCreateMCJITCompilerForModule(LLVMExecutionEngineRef *OutJIT, LLVMModuleRef M, LLVMMCJITCompilerOptions *PassedOptions, size_t SizeOfPassedOptions, char **OutError); -extern "C" bool +bool 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); -extern "C" void +void aot_func_disable_tce(LLVMValueRef func); +void +aot_apply_llvm_new_pass_manager(AOTCompContext *comp_ctx); +} + +static TargetMachine * +unwrap(LLVMTargetMachineRef P) +{ + return reinterpret_cast(P); +} + LLVMBool WAMRCreateMCJITCompilerForModule(LLVMExecutionEngineRef *OutJIT, LLVMModuleRef M, @@ -334,3 +360,121 @@ aot_func_disable_tce(LLVMValueRef func) "disable-tail-calls", "true"); 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 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 +} diff --git a/core/iwasm/include/aot_export.h b/core/iwasm/include/aot_export.h index d71f945f5d..e0ee896681 100644 --- a/core/iwasm/include/aot_export.h +++ b/core/iwasm/include/aot_export.h @@ -83,17 +83,6 @@ aot_emit_aot_file(aot_comp_context_t comp_ctx, aot_comp_data_t comp_data, void 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 * aot_get_last_error(); diff --git a/wamr-compiler/CMakeLists.txt b/wamr-compiler/CMakeLists.txt index 8d943d97e6..edec4c7a52 100644 --- a/wamr-compiler/CMakeLists.txt +++ b/wamr-compiler/CMakeLists.txt @@ -36,6 +36,10 @@ add_definitions(-DWASM_ENABLE_CUSTOM_NAME_SECTION=1) add_definitions(-DWASM_ENABLE_DUMP_CALL_STACK=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: # "X86_64", "AMD_64", "X86_32", "ARM_32", "MIPS_32", "XTENSA_32" if (NOT WAMR_BUILD_TARGET)