diff --git a/core/iwasm/aot/aot_intrinsic.c b/core/iwasm/aot/aot_intrinsic.c index 7ac4b4743..5d27fc9e0 100644 --- a/core/iwasm/aot/aot_intrinsic.c +++ b/core/iwasm/aot/aot_intrinsic.c @@ -69,6 +69,8 @@ static const aot_intrinsic g_intrinsic_mapping[] = { { "f64.const", NULL, AOT_INTRINSIC_FLAG_F64_CONST }, { "i64.div_s", "aot_intrinsic_i64_div_s", AOT_INTRINSIC_FLAG_I64_DIV_S}, { "i32.div_u", "aot_intrinsic_i32_div_u", AOT_INTRINSIC_FLAG_I32_DIV_U}, + { "i32.rem_s", "aot_intrinsic_i32_rem_s", AOT_INTRINSIC_FLAG_I32_REM_S}, + { "i32.rem_u", "aot_intrinsic_i32_rem_u", AOT_INTRINSIC_FLAG_I32_REM_U}, { "i64.div_u", "aot_intrinsic_i64_div_u", AOT_INTRINSIC_FLAG_I64_DIV_U}, { "i64.rem_s", "aot_intrinsic_i64_rem_s", AOT_INTRINSIC_FLAG_I64_REM_S}, { "i64.rem_u", "aot_intrinsic_i64_rem_u", AOT_INTRINSIC_FLAG_I64_REM_U}, @@ -508,6 +510,18 @@ aot_intrinsic_i32_div_u(uint32 l, uint32 r) return l / r; } +int32 +aot_intrinsic_i32_rem_s(int32 l, int32 r) +{ + return l % r; +} + +uint32 +aot_intrinsic_i32_rem_u(uint32 l, uint32 r) +{ + return l % r; +} + uint64 aot_intrinsic_i64_div_u(uint64 l, uint64 r) { @@ -580,6 +594,8 @@ static void add_i32_common_intrinsics(AOTCompContext *comp_ctx) { add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I32_DIV_U); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I32_REM_S); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I32_REM_U); } static void @@ -675,6 +691,7 @@ aot_intrinsic_fill_capability_flags(AOTCompContext *comp_ctx) return; if (!strncmp(comp_ctx->target_arch, "thumb", 5)) { + add_i32_common_intrinsics(comp_ctx); if (!strcmp(comp_ctx->target_cpu, "cortex-m7")) { } else if (!strcmp(comp_ctx->target_cpu, "cortex-m4")) { diff --git a/core/iwasm/aot/aot_intrinsic.h b/core/iwasm/aot/aot_intrinsic.h index ae66037f2..553d67247 100644 --- a/core/iwasm/aot/aot_intrinsic.h +++ b/core/iwasm/aot/aot_intrinsic.h @@ -60,6 +60,8 @@ extern "C" { #define AOT_INTRINSIC_FLAG_F32_CONST AOT_INTRINSIC_FLAG(0, 26) #define AOT_INTRINSIC_FLAG_I32_CONST AOT_INTRINSIC_FLAG(0, 27) #define AOT_INTRINSIC_FLAG_I32_DIV_U AOT_INTRINSIC_FLAG(0, 28) +#define AOT_INTRINSIC_FLAG_I32_REM_S AOT_INTRINSIC_FLAG(0, 29) +#define AOT_INTRINSIC_FLAG_I32_REM_U AOT_INTRINSIC_FLAG(0, 30) #define AOT_INTRINSIC_FLAG_F64_FADD AOT_INTRINSIC_FLAG(1, 0) #define AOT_INTRINSIC_FLAG_F64_FSUB AOT_INTRINSIC_FLAG(1, 1) @@ -260,6 +262,12 @@ aot_intrinsic_i64_div_s(int64 l, int64 r); uint32 aot_intrinsic_i32_div_u(uint32 l, uint32 r); +int32 +aot_intrinsic_i32_rem_s(int32 l, int32 r); + +uint32 +aot_intrinsic_i32_rem_u(uint32 l, uint32 r); + uint64 aot_intrinsic_i64_div_u(uint64 l, uint64 r); diff --git a/core/iwasm/aot/aot_reloc.h b/core/iwasm/aot/aot_reloc.h index 1ae52302c..41f83bb62 100644 --- a/core/iwasm/aot/aot_reloc.h +++ b/core/iwasm/aot/aot_reloc.h @@ -115,6 +115,8 @@ typedef struct { REG_SYM(aot_intrinsic_i64_bit_or), \ REG_SYM(aot_intrinsic_i64_bit_and), \ REG_SYM(aot_intrinsic_i32_div_u), \ + REG_SYM(aot_intrinsic_i32_rem_s), \ + REG_SYM(aot_intrinsic_i32_rem_u), \ #define REG_COMMON_SYMBOLS \ REG_SYM(aot_set_exception_with_id), \ diff --git a/core/iwasm/compilation/aot_emit_numberic.c b/core/iwasm/compilation/aot_emit_numberic.c index d9bfca517..396fc0e9e 100644 --- a/core/iwasm/compilation/aot_emit_numberic.c +++ b/core/iwasm/compilation/aot_emit_numberic.c @@ -31,7 +31,7 @@ #define LLVM_BUILD_OP_OR_INTRINSIC(Op, left, right, res, intrinsic, name, \ err_ret) \ do { \ - if (comp_ctx->disable_llvm_intrinsics && !is_i32 \ + 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, \ @@ -234,8 +234,6 @@ compile_op_float_min_max(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, nan = LLVMConstRealOfString(ret_type, "NaN"); char *intrinsic = is_min ? (is_f32 ? "llvm.minnum.f32" : "llvm.minnum.f64") : (is_f32 ? "llvm.maxnum.f32" : "llvm.maxnum.f64"); - bool is_i32 = is_f32; - CHECK_LLVM_CONST(nan); param_types[0] = param_types[1] = ret_type; @@ -292,11 +290,13 @@ compile_op_float_min_max(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, } if (is_min) - LLVM_BUILD_OP_OR_INTRINSIC(Or, left_int, right_int, tmp, "i64.or", - "tmp_int", false); + LLVM_BUILD_OP_OR_INTRINSIC(Or, left_int, right_int, tmp, + is_f32 ? "i32.or" : "i64.or", "tmp_int", + false); else - LLVM_BUILD_OP_OR_INTRINSIC(And, left_int, right_int, tmp, "i64.and", - "tmp_int", false); + LLVM_BUILD_OP_OR_INTRINSIC(And, left_int, right_int, tmp, + is_f32 ? "i32.and" : "i64.and", "tmp_int", + false); if (!(tmp = LLVMBuildBitCast(comp_ctx->builder, tmp, ret_type, "tmp"))) { aot_set_last_error("llvm build bitcast fail."); @@ -402,7 +402,8 @@ compile_rems(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, LLVMPositionBuilderAtEnd(comp_ctx->builder, no_overflow_block); LLVM_BUILD_OP_OR_INTRINSIC(SRem, left, right, no_overflow_value, - "i64.rem_s", "rem_s", false); + is_i32 ? "i32.rem_s" : "i64.rem_s", "rem_s", + false); /* Jump to rems_end block */ if (!LLVMBuildBr(comp_ctx->builder, rems_end_block)) { @@ -516,20 +517,24 @@ compile_int_div(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, /* Build div */ switch (arith_op) { case INT_DIV_S: - LLVM_BUILD_OP_OR_INTRINSIC(SDiv, left, right, res, - "i64.div_s", "div_s", false); + LLVM_BUILD_OP_OR_INTRINSIC( + SDiv, left, right, res, + is_i32 ? "i32.div_s" : "i64.div_s", "div_s", false); break; case INT_DIV_U: - LLVM_BUILD_OP_OR_INTRINSIC(UDiv, left, right, res, - "i64.div_u", "div_u", false); + LLVM_BUILD_OP_OR_INTRINSIC( + UDiv, left, right, res, + is_i32 ? "i32.div_u" : "i64.div_u", "div_u", false); break; case INT_REM_S: - LLVM_BUILD_OP_OR_INTRINSIC(SRem, left, right, res, - "i64.rem_s", "rem_s", false); + LLVM_BUILD_OP_OR_INTRINSIC( + SRem, left, right, res, + is_i32 ? "i32.rem_s" : "i64.rem_s", "rem_s", false); break; case INT_REM_U: - LLVM_BUILD_OP_OR_INTRINSIC(URem, left, right, res, - "i64.rem_u", "rem_u", false); + LLVM_BUILD_OP_OR_INTRINSIC( + URem, left, right, res, + is_i32 ? "i32.rem_u" : "i64.rem_u", "rem_u", false); break; default: bh_assert(0); @@ -568,7 +573,8 @@ compile_int_div(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, check_overflow_succ))) goto fail; - LLVM_BUILD_OP_OR_INTRINSIC(SDiv, left, right, res, "i64.div_s", + LLVM_BUILD_OP_OR_INTRINSIC(SDiv, left, right, res, + is_i32 ? "i32.div_s" : "i64.div_s", "div_s", false); PUSH_INT(res); return true; @@ -594,7 +600,8 @@ 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_OR_INTRINSIC(URem, left, right, res, "i64.rem_u", + LLVM_BUILD_OP_OR_INTRINSIC(URem, left, right, res, + is_i32 ? "i32.rem_u" : "i64.rem_u", "rem_u", false); PUSH_INT(res); return true;