Implement i32.rem_s and i32.rem_u intrinsic (#1789)

This commit is contained in:
Huang Qi 2022-12-08 09:38:20 +08:00 committed by Wenyong Huang
parent ead6478285
commit bfd57558a7
4 changed files with 52 additions and 18 deletions

View File

@ -69,6 +69,8 @@ static const aot_intrinsic g_intrinsic_mapping[] = {
{ "f64.const", NULL, AOT_INTRINSIC_FLAG_F64_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_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.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.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_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}, { "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; 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 uint64
aot_intrinsic_i64_div_u(uint64 l, uint64 r) aot_intrinsic_i64_div_u(uint64 l, uint64 r)
{ {
@ -580,6 +594,8 @@ static void
add_i32_common_intrinsics(AOTCompContext *comp_ctx) 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_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 static void
@ -675,6 +691,7 @@ aot_intrinsic_fill_capability_flags(AOTCompContext *comp_ctx)
return; return;
if (!strncmp(comp_ctx->target_arch, "thumb", 5)) { if (!strncmp(comp_ctx->target_arch, "thumb", 5)) {
add_i32_common_intrinsics(comp_ctx);
if (!strcmp(comp_ctx->target_cpu, "cortex-m7")) { if (!strcmp(comp_ctx->target_cpu, "cortex-m7")) {
} }
else if (!strcmp(comp_ctx->target_cpu, "cortex-m4")) { else if (!strcmp(comp_ctx->target_cpu, "cortex-m4")) {

View File

@ -60,6 +60,8 @@ extern "C" {
#define AOT_INTRINSIC_FLAG_F32_CONST AOT_INTRINSIC_FLAG(0, 26) #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_CONST AOT_INTRINSIC_FLAG(0, 27)
#define AOT_INTRINSIC_FLAG_I32_DIV_U AOT_INTRINSIC_FLAG(0, 28) #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_FADD AOT_INTRINSIC_FLAG(1, 0)
#define AOT_INTRINSIC_FLAG_F64_FSUB AOT_INTRINSIC_FLAG(1, 1) #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 uint32
aot_intrinsic_i32_div_u(uint32 l, uint32 r); 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 uint64
aot_intrinsic_i64_div_u(uint64 l, uint64 r); aot_intrinsic_i64_div_u(uint64 l, uint64 r);

View File

@ -115,6 +115,8 @@ typedef struct {
REG_SYM(aot_intrinsic_i64_bit_or), \ REG_SYM(aot_intrinsic_i64_bit_or), \
REG_SYM(aot_intrinsic_i64_bit_and), \ REG_SYM(aot_intrinsic_i64_bit_and), \
REG_SYM(aot_intrinsic_i32_div_u), \ 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 \ #define REG_COMMON_SYMBOLS \
REG_SYM(aot_set_exception_with_id), \ REG_SYM(aot_set_exception_with_id), \

View File

@ -31,7 +31,7 @@
#define LLVM_BUILD_OP_OR_INTRINSIC(Op, left, right, res, intrinsic, name, \ #define LLVM_BUILD_OP_OR_INTRINSIC(Op, left, right, res, intrinsic, name, \
err_ret) \ err_ret) \
do { \ do { \
if (comp_ctx->disable_llvm_intrinsics && !is_i32 \ if (comp_ctx->disable_llvm_intrinsics \
&& aot_intrinsic_check_capability(comp_ctx, intrinsic)) { \ && aot_intrinsic_check_capability(comp_ctx, intrinsic)) { \
res = aot_call_llvm_intrinsic(comp_ctx, func_ctx, intrinsic, \ res = aot_call_llvm_intrinsic(comp_ctx, func_ctx, intrinsic, \
param_types[0], param_types, 2, \ 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"); nan = LLVMConstRealOfString(ret_type, "NaN");
char *intrinsic = is_min ? (is_f32 ? "llvm.minnum.f32" : "llvm.minnum.f64") char *intrinsic = is_min ? (is_f32 ? "llvm.minnum.f32" : "llvm.minnum.f64")
: (is_f32 ? "llvm.maxnum.f32" : "llvm.maxnum.f64"); : (is_f32 ? "llvm.maxnum.f32" : "llvm.maxnum.f64");
bool is_i32 = is_f32;
CHECK_LLVM_CONST(nan); CHECK_LLVM_CONST(nan);
param_types[0] = param_types[1] = ret_type; 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) if (is_min)
LLVM_BUILD_OP_OR_INTRINSIC(Or, left_int, right_int, tmp, "i64.or", LLVM_BUILD_OP_OR_INTRINSIC(Or, left_int, right_int, tmp,
"tmp_int", false); is_f32 ? "i32.or" : "i64.or", "tmp_int",
false);
else else
LLVM_BUILD_OP_OR_INTRINSIC(And, left_int, right_int, tmp, "i64.and", LLVM_BUILD_OP_OR_INTRINSIC(And, left_int, right_int, tmp,
"tmp_int", false); is_f32 ? "i32.and" : "i64.and", "tmp_int",
false);
if (!(tmp = LLVMBuildBitCast(comp_ctx->builder, tmp, ret_type, "tmp"))) { if (!(tmp = LLVMBuildBitCast(comp_ctx->builder, tmp, ret_type, "tmp"))) {
aot_set_last_error("llvm build bitcast fail."); 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); LLVMPositionBuilderAtEnd(comp_ctx->builder, no_overflow_block);
LLVM_BUILD_OP_OR_INTRINSIC(SRem, left, right, no_overflow_value, 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 */ /* Jump to rems_end block */
if (!LLVMBuildBr(comp_ctx->builder, 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 */ /* Build div */
switch (arith_op) { switch (arith_op) {
case INT_DIV_S: case INT_DIV_S:
LLVM_BUILD_OP_OR_INTRINSIC(SDiv, left, right, res, LLVM_BUILD_OP_OR_INTRINSIC(
"i64.div_s", "div_s", false); SDiv, left, right, res,
is_i32 ? "i32.div_s" : "i64.div_s", "div_s", false);
break; break;
case INT_DIV_U: case INT_DIV_U:
LLVM_BUILD_OP_OR_INTRINSIC(UDiv, left, right, res, LLVM_BUILD_OP_OR_INTRINSIC(
"i64.div_u", "div_u", false); UDiv, left, right, res,
is_i32 ? "i32.div_u" : "i64.div_u", "div_u", false);
break; break;
case INT_REM_S: case INT_REM_S:
LLVM_BUILD_OP_OR_INTRINSIC(SRem, left, right, res, LLVM_BUILD_OP_OR_INTRINSIC(
"i64.rem_s", "rem_s", false); SRem, left, right, res,
is_i32 ? "i32.rem_s" : "i64.rem_s", "rem_s", false);
break; break;
case INT_REM_U: case INT_REM_U:
LLVM_BUILD_OP_OR_INTRINSIC(URem, left, right, res, LLVM_BUILD_OP_OR_INTRINSIC(
"i64.rem_u", "rem_u", false); URem, left, right, res,
is_i32 ? "i32.rem_u" : "i64.rem_u", "rem_u", false);
break; break;
default: default:
bh_assert(0); bh_assert(0);
@ -568,7 +573,8 @@ compile_int_div(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
check_overflow_succ))) check_overflow_succ)))
goto fail; 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); "div_s", false);
PUSH_INT(res); PUSH_INT(res);
return true; 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, return compile_rems(comp_ctx, func_ctx, left, right, overflow,
is_i32); is_i32);
case INT_REM_U: 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); "rem_u", false);
PUSH_INT(res); PUSH_INT(res);
return true; return true;