diff --git a/core/iwasm/aot/aot_intrinsic.c b/core/iwasm/aot/aot_intrinsic.c index a4af9de3d..eed327485 100644 --- a/core/iwasm/aot/aot_intrinsic.c +++ b/core/iwasm/aot/aot_intrinsic.c @@ -65,6 +65,10 @@ static const aot_intrinsic g_intrinsic_mapping[] = { { "i64.const", NULL, AOT_INTRINSIC_FLAG_I64_CONST }, { "f32.const", NULL, AOT_INTRINSIC_FLAG_F32_CONST }, { "f64.const", NULL, AOT_INTRINSIC_FLAG_F64_CONST }, + { "i64.div_s", "aot_intrinsic_i64_div_s", AOT_INTRINSIC_FLAG_I64_DIV_S}, + { "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}, }; /* clang-format on */ @@ -487,6 +491,30 @@ aot_intrinsic_f64_cmp(AOTFloatCond cond, float64 lhs, float64 rhs) return 0; } +int64 +aot_intrinsic_i64_div_s(int64 l, int64 r) +{ + return l / r; +} + +uint64 +aot_intrinsic_i64_div_u(uint64 l, uint64 r) +{ + return l / r; +} + +int64 +aot_intrinsic_i64_rem_s(int64 l, int64 r) +{ + return l % r; +} + +uint64 +aot_intrinsic_i64_rem_u(uint64 l, uint64 r) +{ + return l % r; +} + const char * aot_intrinsic_get_symbol(const char *llvm_intrinsic) { @@ -514,6 +542,15 @@ add_intrinsic_capability(AOTCompContext *comp_ctx, uint64 flag) } } +static void +add_i64_common_intrinsics(AOTCompContext *comp_ctx) +{ + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I64_DIV_S); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I64_DIV_U); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I64_REM_S); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I64_REM_U); +} + static void add_f32_common_intrinsics(AOTCompContext *comp_ctx) { @@ -621,6 +658,9 @@ aot_intrinsic_fill_capability_flags(AOTCompContext *comp_ctx) add_f64_common_intrinsics(comp_ctx); add_common_float_integer_convertion(comp_ctx); } + else if (!strncmp(comp_ctx->target_arch, "riscv32", 7)) { + add_i64_common_intrinsics(comp_ctx); + } else if (!strncmp(comp_ctx->target_arch, "xtensa", 6)) { /* * Note: Use builtin intrinsics since hardware float operation diff --git a/core/iwasm/aot/aot_intrinsic.h b/core/iwasm/aot/aot_intrinsic.h index b21e77597..92dccea09 100644 --- a/core/iwasm/aot/aot_intrinsic.h +++ b/core/iwasm/aot/aot_intrinsic.h @@ -88,6 +88,11 @@ extern "C" { #define AOT_INTRINSIC_FLAG_F64_CMP AOT_INTRINSIC_FLAG(1, 25) #define AOT_INTRINSIC_FLAG_F64_CONST AOT_INTRINSIC_FLAG(1, 26) #define AOT_INTRINSIC_FLAG_I64_CONST AOT_INTRINSIC_FLAG(1, 27) +#define AOT_INTRINSIC_FLAG_I64_DIV_S AOT_INTRINSIC_FLAG(1, 28) +#define AOT_INTRINSIC_FLAG_I64_DIV_U AOT_INTRINSIC_FLAG(1, 29) +#define AOT_INTRINSIC_FLAG_I64_REM_S AOT_INTRINSIC_FLAG(1, 30) +#define AOT_INTRINSIC_FLAG_I64_REM_U AOT_INTRINSIC_FLAG(1, 31) + /* clang-format on */ float32 @@ -246,6 +251,18 @@ aot_intrinsic_f32_cmp(AOTFloatCond cond, float32 lhs, float32 rhs); int32 aot_intrinsic_f64_cmp(AOTFloatCond cond, float64 lhs, float64 rhs); +int64 +aot_intrinsic_i64_div_s(int64 l, int64 r); + +uint64 +aot_intrinsic_i64_div_u(uint64 l, uint64 r); + +int64 +aot_intrinsic_i64_rem_s(int64 l, int64 r); + +uint64 +aot_intrinsic_i64_rem_u(uint64 l, uint64 r); + const char * aot_intrinsic_get_symbol(const char *llvm_intrinsic); diff --git a/core/iwasm/aot/aot_reloc.h b/core/iwasm/aot/aot_reloc.h index 471bf9c01..f97cea723 100644 --- a/core/iwasm/aot/aot_reloc.h +++ b/core/iwasm/aot/aot_reloc.h @@ -106,6 +106,10 @@ typedef struct { REG_SYM(aot_intrinsic_f32_to_f64), \ REG_SYM(aot_intrinsic_f32_cmp), \ REG_SYM(aot_intrinsic_f64_cmp), \ + REG_SYM(aot_intrinsic_i64_div_s), \ + REG_SYM(aot_intrinsic_i64_div_u), \ + REG_SYM(aot_intrinsic_i64_rem_s), \ + REG_SYM(aot_intrinsic_i64_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 3ddd8cea3..09ad1c50c 100644 --- a/core/iwasm/compilation/aot_emit_numberic.c +++ b/core/iwasm/compilation/aot_emit_numberic.c @@ -388,6 +388,9 @@ 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]; + + param_types[1] = param_types[0] = is_i32 ? I32_TYPE : I64_TYPE; bh_assert(arith_op == INT_DIV_S || arith_op == INT_DIV_U || arith_op == INT_REM_S || arith_op == INT_REM_U); @@ -459,16 +462,56 @@ compile_int_div(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, /* Build div */ switch (arith_op) { case INT_DIV_S: - 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); + } break; case INT_DIV_U: - LLVM_BUILD_OP(UDiv, left, right, res, "div_u", false); + 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); + } + else { + LLVM_BUILD_OP(UDiv, left, right, res, "div_u", + false); + } break; case INT_REM_S: - LLVM_BUILD_OP(SRem, left, right, res, "rem_s", false); + if (comp_ctx->disable_llvm_intrinsics && !is_i32 + && aot_intrinsic_check_capability(comp_ctx, + "i64.rem_s")) { + res = aot_call_llvm_intrinsic( + comp_ctx, func_ctx, "i64.rem_s", param_types[0], + param_types, 2, left, right); + } + else { + LLVM_BUILD_OP(SRem, left, right, res, "rem_s", + false); + } break; 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); + } break; default: bh_assert(0);