From 94cecbe4cbfd7349d7c100c956d14ed664c6a84b Mon Sep 17 00:00:00 2001 From: Huang Qi Date: Tue, 1 Nov 2022 20:29:07 +0800 Subject: [PATCH] Fix XIP issues of fp to int cast and int rem/div (#1654) --- core/iwasm/aot/aot_intrinsic.c | 3 ++ core/iwasm/aot/aot_reloc.h | 2 + core/iwasm/compilation/aot_emit_conversion.c | 28 ++++++++++++-- core/iwasm/compilation/aot_emit_numberic.c | 39 +++++++++++++------- 4 files changed, 54 insertions(+), 18 deletions(-) diff --git a/core/iwasm/aot/aot_intrinsic.c b/core/iwasm/aot/aot_intrinsic.c index 5ce9919a..54669cbd 100644 --- a/core/iwasm/aot/aot_intrinsic.c +++ b/core/iwasm/aot/aot_intrinsic.c @@ -57,6 +57,8 @@ static const aot_intrinsic g_intrinsic_mapping[] = { { "i32_trunc_f32_s", "aot_intrinsic_f32_to_i32", AOT_INTRINSIC_FLAG_F32_TO_I32 }, { "i32_trunc_f64_u", "aot_intrinsic_f64_to_u32", AOT_INTRINSIC_FLAG_F64_TO_U32 }, { "i32_trunc_f64_s", "aot_intrinsic_f64_to_i32", AOT_INTRINSIC_FLAG_F64_TO_I32 }, + { "i64_trunc_f64_u", "aot_intrinsic_f64_to_u64", AOT_INTRINSIC_FLAG_F64_TO_U64 }, + { "i64_trunc_f64_s", "aot_intrinsic_f64_to_i64", AOT_INTRINSIC_FLAG_F64_TO_I64 }, { "f32_demote_f64", "aot_intrinsic_f64_to_f32", AOT_INTRINSIC_FLAG_F64_TO_F32 }, { "f64_promote_f32", "aot_intrinsic_f32_to_f64", AOT_INTRINSIC_FLAG_F32_TO_F64 }, { "f32_cmp", "aot_intrinsic_f32_cmp", AOT_INTRINSIC_FLAG_F32_CMP }, @@ -665,6 +667,7 @@ aot_intrinsic_fill_capability_flags(AOTCompContext *comp_ctx) else { add_f32_common_intrinsics(comp_ctx); add_f64_common_intrinsics(comp_ctx); + add_i64_common_intrinsics(comp_ctx); add_common_float_integer_convertion(comp_ctx); } } diff --git a/core/iwasm/aot/aot_reloc.h b/core/iwasm/aot/aot_reloc.h index 3009af29..1d97c99f 100644 --- a/core/iwasm/aot/aot_reloc.h +++ b/core/iwasm/aot/aot_reloc.h @@ -103,6 +103,8 @@ typedef struct { REG_SYM(aot_intrinsic_f32_to_u32), \ REG_SYM(aot_intrinsic_f64_to_i32), \ REG_SYM(aot_intrinsic_f64_to_u32), \ + REG_SYM(aot_intrinsic_f64_to_i64), \ + REG_SYM(aot_intrinsic_f64_to_u64), \ REG_SYM(aot_intrinsic_f32_to_f64), \ REG_SYM(aot_intrinsic_f32_cmp), \ REG_SYM(aot_intrinsic_f64_cmp), \ diff --git a/core/iwasm/compilation/aot_emit_conversion.c b/core/iwasm/compilation/aot_emit_conversion.c index a1171110..56319380 100644 --- a/core/iwasm/compilation/aot_emit_conversion.c +++ b/core/iwasm/compilation/aot_emit_conversion.c @@ -261,10 +261,30 @@ trunc_sat_float_to_int(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, param_types, 1, operand); } else { - if (sign) - res = LLVMBuildFPToSI(comp_ctx->builder, operand, dest_type, name); - else - res = LLVMBuildFPToUI(comp_ctx->builder, operand, dest_type, name); + char intrinsic[128]; + + /* Integer width is always 32 or 64 here. */ + + snprintf(intrinsic, sizeof(intrinsic), "i%d_trunc_f%d_%c", + LLVMGetIntTypeWidth(dest_type), + LLVMGetTypeKind(src_type) == LLVMFloatTypeKind ? 32 : 64, + sign ? 's' : 'u'); + + if (comp_ctx->disable_llvm_intrinsics + && aot_intrinsic_check_capability(comp_ctx, intrinsic)) { + res = aot_call_llvm_intrinsic(comp_ctx, func_ctx, intrinsic, + dest_type, &src_type, 1, operand); + } + else { + if (sign) { + res = LLVMBuildFPToSI(comp_ctx->builder, operand, dest_type, + name); + } + else { + res = LLVMBuildFPToUI(comp_ctx->builder, operand, dest_type, + name); + } + } } if (!res) { diff --git a/core/iwasm/compilation/aot_emit_numberic.c b/core/iwasm/compilation/aot_emit_numberic.c index 14935e34..3ab61c41 100644 --- a/core/iwasm/compilation/aot_emit_numberic.c +++ b/core/iwasm/compilation/aot_emit_numberic.c @@ -400,6 +400,7 @@ compile_int_div(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, LLVMValueRef left, right, cmp_div_zero, overflow, res; LLVMBasicBlockRef check_div_zero_succ, check_overflow_succ; LLVMTypeRef param_types[2]; + const char *intrinsic = NULL; param_types[1] = param_types[0] = is_i32 ? I32_TYPE : I64_TYPE; @@ -561,22 +562,24 @@ compile_int_div(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, check_overflow_succ))) goto fail; - LLVM_BUILD_OP(SDiv, left, right, res, "div_s", false); + if (comp_ctx->disable_llvm_intrinsics && !is_i32 + && aot_intrinsic_check_capability(comp_ctx, "i64.div_s")) { + res = aot_call_llvm_intrinsic(comp_ctx, func_ctx, + "i64.div_s", param_types[0], + param_types, 2, left, right); + } + else { + LLVM_BUILD_OP(SDiv, left, right, res, "div_s", false); + } PUSH_INT(res); return true; case INT_DIV_U: - if (comp_ctx->disable_llvm_intrinsics && is_i32 - && aot_intrinsic_check_capability(comp_ctx, "i32.div_u")) { - res = aot_call_llvm_intrinsic(comp_ctx, func_ctx, - "i32.div_u", param_types[0], - param_types, 2, left, right); - } - else if (comp_ctx->disable_llvm_intrinsics && !is_i32 - && aot_intrinsic_check_capability(comp_ctx, - "i64.div_u")) { - res = aot_call_llvm_intrinsic(comp_ctx, func_ctx, - "i64.div_u", param_types[0], - param_types, 2, left, right); + intrinsic = is_i32 ? "i32.div_u" : "i64.div_u"; + if (comp_ctx->disable_llvm_intrinsics + && aot_intrinsic_check_capability(comp_ctx, intrinsic)) { + res = aot_call_llvm_intrinsic(comp_ctx, func_ctx, intrinsic, + param_types[0], param_types, + 2, left, right); } else { LLVM_BUILD_OP(UDiv, left, right, res, "div_u", false); @@ -592,7 +595,15 @@ compile_int_div(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, return compile_rems(comp_ctx, func_ctx, left, right, overflow, is_i32); case INT_REM_U: - LLVM_BUILD_OP(URem, left, right, res, "rem_u", false); + if (comp_ctx->disable_llvm_intrinsics && !is_i32 + && aot_intrinsic_check_capability(comp_ctx, "i64.rem_u")) { + res = aot_call_llvm_intrinsic(comp_ctx, func_ctx, + "i64.rem_u", param_types[0], + param_types, 2, left, right); + } + else { + LLVM_BUILD_OP(URem, left, right, res, "rem_u", false); + } PUSH_INT(res); return true; default: