Skip to content

Commit f6bef1e

Browse files
authored
Implement i32.rem_s and i32.rem_u intrinsic (#1789)
1 parent c3d66f9 commit f6bef1e

File tree

4 files changed

+52
-18
lines changed

4 files changed

+52
-18
lines changed

core/iwasm/aot/aot_intrinsic.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ static const aot_intrinsic g_intrinsic_mapping[] = {
6969
{ "f64.const", NULL, AOT_INTRINSIC_FLAG_F64_CONST },
7070
{ "i64.div_s", "aot_intrinsic_i64_div_s", AOT_INTRINSIC_FLAG_I64_DIV_S},
7171
{ "i32.div_u", "aot_intrinsic_i32_div_u", AOT_INTRINSIC_FLAG_I32_DIV_U},
72+
{ "i32.rem_s", "aot_intrinsic_i32_rem_s", AOT_INTRINSIC_FLAG_I32_REM_S},
73+
{ "i32.rem_u", "aot_intrinsic_i32_rem_u", AOT_INTRINSIC_FLAG_I32_REM_U},
7274
{ "i64.div_u", "aot_intrinsic_i64_div_u", AOT_INTRINSIC_FLAG_I64_DIV_U},
7375
{ "i64.rem_s", "aot_intrinsic_i64_rem_s", AOT_INTRINSIC_FLAG_I64_REM_S},
7476
{ "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)
508510
return l / r;
509511
}
510512

513+
int32
514+
aot_intrinsic_i32_rem_s(int32 l, int32 r)
515+
{
516+
return l % r;
517+
}
518+
519+
uint32
520+
aot_intrinsic_i32_rem_u(uint32 l, uint32 r)
521+
{
522+
return l % r;
523+
}
524+
511525
uint64
512526
aot_intrinsic_i64_div_u(uint64 l, uint64 r)
513527
{
@@ -580,6 +594,8 @@ static void
580594
add_i32_common_intrinsics(AOTCompContext *comp_ctx)
581595
{
582596
add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I32_DIV_U);
597+
add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I32_REM_S);
598+
add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I32_REM_U);
583599
}
584600

585601
static void
@@ -675,6 +691,7 @@ aot_intrinsic_fill_capability_flags(AOTCompContext *comp_ctx)
675691
return;
676692

677693
if (!strncmp(comp_ctx->target_arch, "thumb", 5)) {
694+
add_i32_common_intrinsics(comp_ctx);
678695
if (!strcmp(comp_ctx->target_cpu, "cortex-m7")) {
679696
}
680697
else if (!strcmp(comp_ctx->target_cpu, "cortex-m4")) {

core/iwasm/aot/aot_intrinsic.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ extern "C" {
6060
#define AOT_INTRINSIC_FLAG_F32_CONST AOT_INTRINSIC_FLAG(0, 26)
6161
#define AOT_INTRINSIC_FLAG_I32_CONST AOT_INTRINSIC_FLAG(0, 27)
6262
#define AOT_INTRINSIC_FLAG_I32_DIV_U AOT_INTRINSIC_FLAG(0, 28)
63+
#define AOT_INTRINSIC_FLAG_I32_REM_S AOT_INTRINSIC_FLAG(0, 29)
64+
#define AOT_INTRINSIC_FLAG_I32_REM_U AOT_INTRINSIC_FLAG(0, 30)
6365

6466
#define AOT_INTRINSIC_FLAG_F64_FADD AOT_INTRINSIC_FLAG(1, 0)
6567
#define AOT_INTRINSIC_FLAG_F64_FSUB AOT_INTRINSIC_FLAG(1, 1)
@@ -260,6 +262,12 @@ aot_intrinsic_i64_div_s(int64 l, int64 r);
260262
uint32
261263
aot_intrinsic_i32_div_u(uint32 l, uint32 r);
262264

265+
int32
266+
aot_intrinsic_i32_rem_s(int32 l, int32 r);
267+
268+
uint32
269+
aot_intrinsic_i32_rem_u(uint32 l, uint32 r);
270+
263271
uint64
264272
aot_intrinsic_i64_div_u(uint64 l, uint64 r);
265273

core/iwasm/aot/aot_reloc.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ typedef struct {
115115
REG_SYM(aot_intrinsic_i64_bit_or), \
116116
REG_SYM(aot_intrinsic_i64_bit_and), \
117117
REG_SYM(aot_intrinsic_i32_div_u), \
118+
REG_SYM(aot_intrinsic_i32_rem_s), \
119+
REG_SYM(aot_intrinsic_i32_rem_u), \
118120

119121
#define REG_COMMON_SYMBOLS \
120122
REG_SYM(aot_set_exception_with_id), \

core/iwasm/compilation/aot_emit_numberic.c

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
#define LLVM_BUILD_OP_OR_INTRINSIC(Op, left, right, res, intrinsic, name, \
3232
err_ret) \
3333
do { \
34-
if (comp_ctx->disable_llvm_intrinsics && !is_i32 \
34+
if (comp_ctx->disable_llvm_intrinsics \
3535
&& aot_intrinsic_check_capability(comp_ctx, intrinsic)) { \
3636
res = aot_call_llvm_intrinsic(comp_ctx, func_ctx, intrinsic, \
3737
param_types[0], param_types, 2, \
@@ -234,8 +234,6 @@ compile_op_float_min_max(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
234234
nan = LLVMConstRealOfString(ret_type, "NaN");
235235
char *intrinsic = is_min ? (is_f32 ? "llvm.minnum.f32" : "llvm.minnum.f64")
236236
: (is_f32 ? "llvm.maxnum.f32" : "llvm.maxnum.f64");
237-
bool is_i32 = is_f32;
238-
239237
CHECK_LLVM_CONST(nan);
240238

241239
param_types[0] = param_types[1] = ret_type;
@@ -292,11 +290,13 @@ compile_op_float_min_max(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
292290
}
293291

294292
if (is_min)
295-
LLVM_BUILD_OP_OR_INTRINSIC(Or, left_int, right_int, tmp, "i64.or",
296-
"tmp_int", false);
293+
LLVM_BUILD_OP_OR_INTRINSIC(Or, left_int, right_int, tmp,
294+
is_f32 ? "i32.or" : "i64.or", "tmp_int",
295+
false);
297296
else
298-
LLVM_BUILD_OP_OR_INTRINSIC(And, left_int, right_int, tmp, "i64.and",
299-
"tmp_int", false);
297+
LLVM_BUILD_OP_OR_INTRINSIC(And, left_int, right_int, tmp,
298+
is_f32 ? "i32.and" : "i64.and", "tmp_int",
299+
false);
300300

301301
if (!(tmp = LLVMBuildBitCast(comp_ctx->builder, tmp, ret_type, "tmp"))) {
302302
aot_set_last_error("llvm build bitcast fail.");
@@ -402,7 +402,8 @@ compile_rems(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
402402
LLVMPositionBuilderAtEnd(comp_ctx->builder, no_overflow_block);
403403

404404
LLVM_BUILD_OP_OR_INTRINSIC(SRem, left, right, no_overflow_value,
405-
"i64.rem_s", "rem_s", false);
405+
is_i32 ? "i32.rem_s" : "i64.rem_s", "rem_s",
406+
false);
406407

407408
/* Jump to rems_end block */
408409
if (!LLVMBuildBr(comp_ctx->builder, rems_end_block)) {
@@ -516,20 +517,24 @@ compile_int_div(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
516517
/* Build div */
517518
switch (arith_op) {
518519
case INT_DIV_S:
519-
LLVM_BUILD_OP_OR_INTRINSIC(SDiv, left, right, res,
520-
"i64.div_s", "div_s", false);
520+
LLVM_BUILD_OP_OR_INTRINSIC(
521+
SDiv, left, right, res,
522+
is_i32 ? "i32.div_s" : "i64.div_s", "div_s", false);
521523
break;
522524
case INT_DIV_U:
523-
LLVM_BUILD_OP_OR_INTRINSIC(UDiv, left, right, res,
524-
"i64.div_u", "div_u", false);
525+
LLVM_BUILD_OP_OR_INTRINSIC(
526+
UDiv, left, right, res,
527+
is_i32 ? "i32.div_u" : "i64.div_u", "div_u", false);
525528
break;
526529
case INT_REM_S:
527-
LLVM_BUILD_OP_OR_INTRINSIC(SRem, left, right, res,
528-
"i64.rem_s", "rem_s", false);
530+
LLVM_BUILD_OP_OR_INTRINSIC(
531+
SRem, left, right, res,
532+
is_i32 ? "i32.rem_s" : "i64.rem_s", "rem_s", false);
529533
break;
530534
case INT_REM_U:
531-
LLVM_BUILD_OP_OR_INTRINSIC(URem, left, right, res,
532-
"i64.rem_u", "rem_u", false);
535+
LLVM_BUILD_OP_OR_INTRINSIC(
536+
URem, left, right, res,
537+
is_i32 ? "i32.rem_u" : "i64.rem_u", "rem_u", false);
533538
break;
534539
default:
535540
bh_assert(0);
@@ -568,7 +573,8 @@ compile_int_div(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
568573
check_overflow_succ)))
569574
goto fail;
570575

571-
LLVM_BUILD_OP_OR_INTRINSIC(SDiv, left, right, res, "i64.div_s",
576+
LLVM_BUILD_OP_OR_INTRINSIC(SDiv, left, right, res,
577+
is_i32 ? "i32.div_s" : "i64.div_s",
572578
"div_s", false);
573579
PUSH_INT(res);
574580
return true;
@@ -594,7 +600,8 @@ compile_int_div(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
594600
return compile_rems(comp_ctx, func_ctx, left, right, overflow,
595601
is_i32);
596602
case INT_REM_U:
597-
LLVM_BUILD_OP_OR_INTRINSIC(URem, left, right, res, "i64.rem_u",
603+
LLVM_BUILD_OP_OR_INTRINSIC(URem, left, right, res,
604+
is_i32 ? "i32.rem_u" : "i64.rem_u",
598605
"rem_u", false);
599606
PUSH_INT(res);
600607
return true;

0 commit comments

Comments
 (0)