| --- a/core/iwasm/compilation/aot_llvm.c | |
| +++ b/core/iwasm/compilation/aot_llvm.c | |
| @@ -3238,9 +3253,17 @@ | |
| else | |
| code_model = LLVMCodeModelSmall; | |
| - /* Create the target machine */ | |
| + /* Create the target machine. The backend level may be pinned below | |
| + the IR level: LLVM's optimizing AArch64 codegen miscompiles the | |
| + strict (constrained) FP this compiler emits, so a build can keep | |
| + IR optimization while selecting instructions conservatively. */ | |
| + uint32 tm_opt_level = opt_level; | |
| + if (option->codegen_opt_level_plus_one != 0 | |
| + && option->codegen_opt_level_plus_one - 1 < tm_opt_level) { | |
| + tm_opt_level = option->codegen_opt_level_plus_one - 1; | |
| + } | |
| if (!(comp_ctx->target_machine = LLVMCreateTargetMachineWithOpts( | |
| - target, triple_norm, cpu, features, opt_level, | |
| + target, triple_norm, cpu, features, tm_opt_level, | |
| LLVMRelocStatic, code_model, false, | |
| comp_ctx->stack_usage_file))) { | |
| aot_set_last_error("create LLVM target machine failed."); | |
| --- a/core/iwasm/include/aot_comp_option.h | |
| +++ b/core/iwasm/include/aot_comp_option.h | |
| @@ -83,6 +83,10 @@ | |
| bool enable_shared_chain; | |
| char *use_prof_file; | |
| uint32_t opt_level; | |
| + /* Backend codegen level override, stored as level + 1 so a zeroed | |
| + struct follows opt_level. Lets a build keep IR optimization while | |
| + pinning conservative instruction selection. */ | |
| + uint32_t codegen_opt_level_plus_one; | |
| uint32_t size_level; | |
| uint32_t output_format; | |
| uint32_t bounds_checks; | |
| --- a/wamr-compiler/main.c | |
| +++ b/wamr-compiler/main.c | |
| @@ -130,6 +130,7 @@ | |
| printf(" For example, --cpu-features=+feature1,-feature2\n"); | |
| printf(" Use --cpu-features=+help to list all the features supported\n"); | |
| printf(" --opt-level=n Set the optimization level (0 to 3, default is 3)\n"); | |
| + printf(" --codegen-opt-level=n Cap the backend codegen level below the IR opt level\n"); | |
| printf(" --size-level=n Set the code size level (0 to 3, default is 3)\n"); | |
| printf(" 0 - Large code model\n"); | |
| printf(" 1 - Medium code model\n"); | |
| @@ -472,6 +473,15 @@ | |
| option.opt_level = (uint32)atoi(argv[0] + 12); | |
| if (option.opt_level > 3) | |
| option.opt_level = 3; | |
| + } | |
| + else if (!strncmp(argv[0], "--codegen-opt-level=", 20)) { | |
| + uint32 level; | |
| + if (argv[0][20] == '\0') | |
| + PRINT_HELP_AND_EXIT(); | |
| + level = (uint32)atoi(argv[0] + 20); | |
| + if (level > 3) | |
| + level = 3; | |
| + option.codegen_opt_level_plus_one = level + 1; | |
| } | |
| else if (!strncmp(argv[0], "--size-level=", 13)) { | |
| if (argv[0][13] == '\0') |