diff --git a/core/iwasm/aot/aot_intrinsic.c b/core/iwasm/aot/aot_intrinsic.c index 5f62abf24..252ef7056 100644 --- a/core/iwasm/aot/aot_intrinsic.c +++ b/core/iwasm/aot/aot_intrinsic.c @@ -485,6 +485,30 @@ aot_intrinsic_i64_bit_and(uint64 l, uint64 r) return l & r; } +uint64 +aot_intrinsic_i64_mul(uint64 l, uint64 r) +{ + return l * r; +} + +uint64 +aot_intrinsic_i64_shl(uint64 l, uint64 r) +{ + return l << r; +} + +uint64 +aot_intrinsic_i64_shr_s(uint64 l, uint64 r) +{ + return (int64)l >> r; +} + +uint64 +aot_intrinsic_i64_shr_u(uint64 l, uint64 r) +{ + return l >> r; +} + #if WASM_ENABLE_WAMR_COMPILER != 0 || WASM_ENABLE_JIT != 0 typedef struct { @@ -561,6 +585,10 @@ static const aot_intrinsic g_intrinsic_mapping[] = { { "i64.rem_u", "aot_intrinsic_i64_rem_u", AOT_INTRINSIC_FLAG_I64_REM_U}, { "i64.or", "aot_intrinsic_i64_bit_or", AOT_INTRINSIC_FLAG_I64_BIT_OR}, { "i64.and", "aot_intrinsic_i64_bit_and", AOT_INTRINSIC_FLAG_I64_BIT_AND}, + { "i64.mul", "aot_intrinsic_i64_mul", AOT_INTRINSIC_FLAG_I64_MUL}, + { "i64.shl", "aot_intrinsic_i64_shl", AOT_INTRINSIC_FLAG_I64_SHL}, + { "i64.shr_s", "aot_intrinsic_i64_shr_s", AOT_INTRINSIC_FLAG_I64_SHR_S}, + { "i64.shr_u", "aot_intrinsic_i64_shr_u", AOT_INTRINSIC_FLAG_I64_SHR_U}, }; /* clang-format on */ @@ -601,6 +629,10 @@ add_i64_common_intrinsics(AOTCompContext *comp_ctx) add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I64_REM_U); add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I64_BIT_OR); add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I64_BIT_AND); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I64_MUL); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I64_SHL); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I64_SHR_S); + add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I64_SHR_U); } static void diff --git a/core/iwasm/aot/aot_intrinsic.h b/core/iwasm/aot/aot_intrinsic.h index 6a456efda..f065a5ad2 100644 --- a/core/iwasm/aot/aot_intrinsic.h +++ b/core/iwasm/aot/aot_intrinsic.h @@ -98,6 +98,10 @@ extern "C" { #define AOT_INTRINSIC_FLAG_I64_REM_U AOT_INTRINSIC_FLAG(1, 31) #define AOT_INTRINSIC_FLAG_I64_BIT_OR AOT_INTRINSIC_FLAG(1, 32) #define AOT_INTRINSIC_FLAG_I64_BIT_AND AOT_INTRINSIC_FLAG(1, 33) +#define AOT_INTRINSIC_FLAG_I64_MUL AOT_INTRINSIC_FLAG(1, 34) +#define AOT_INTRINSIC_FLAG_I64_SHL AOT_INTRINSIC_FLAG(1, 35) +#define AOT_INTRINSIC_FLAG_I64_SHR_S AOT_INTRINSIC_FLAG(1, 36) +#define AOT_INTRINSIC_FLAG_I64_SHR_U AOT_INTRINSIC_FLAG(1, 37) /* clang-format on */ @@ -287,6 +291,18 @@ aot_intrinsic_i64_bit_or(uint64 l, uint64 r); uint64 aot_intrinsic_i64_bit_and(uint64 l, uint64 r); +uint64 +aot_intrinsic_i64_mul(uint64 l, uint64 r); + +uint64 +aot_intrinsic_i64_shl(uint64 l, uint64 r); + +uint64 +aot_intrinsic_i64_shr_s(uint64 l, uint64 r); + +uint64 +aot_intrinsic_i64_shr_u(uint64 l, uint64 r); + #if WASM_ENABLE_WAMR_COMPILER != 0 || WASM_ENABLE_JIT != 0 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 f7ada4d8d..ca9ba17f1 100644 --- a/core/iwasm/aot/aot_reloc.h +++ b/core/iwasm/aot/aot_reloc.h @@ -122,6 +122,10 @@ typedef struct { REG_SYM(aot_intrinsic_i64_rem_u), \ REG_SYM(aot_intrinsic_i64_bit_or), \ REG_SYM(aot_intrinsic_i64_bit_and), \ + REG_SYM(aot_intrinsic_i64_mul), \ + REG_SYM(aot_intrinsic_i64_shl), \ + REG_SYM(aot_intrinsic_i64_shr_s), \ + REG_SYM(aot_intrinsic_i64_shr_u), \ REG_SYM(aot_intrinsic_i32_div_s), \ REG_SYM(aot_intrinsic_i32_div_u), \ REG_SYM(aot_intrinsic_i32_rem_s), \ diff --git a/core/iwasm/compilation/aot_emit_numberic.c b/core/iwasm/compilation/aot_emit_numberic.c index 1f37060d9..492c3048c 100644 --- a/core/iwasm/compilation/aot_emit_numberic.c +++ b/core/iwasm/compilation/aot_emit_numberic.c @@ -653,15 +653,22 @@ compile_int_sub(AOTCompContext *comp_ctx, LLVMValueRef left, LLVMValueRef right, } static LLVMValueRef -compile_int_mul(AOTCompContext *comp_ctx, LLVMValueRef left, LLVMValueRef right, - bool is_i32) +compile_int_mul(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + LLVMValueRef left, LLVMValueRef right, bool is_i32) { /* If one of the operands is 0, just return constant 0 */ if (IS_CONST_ZERO(left) || IS_CONST_ZERO(right)) return is_i32 ? I32_ZERO : I64_ZERO; /* Build mul */ - return LLVMBuildMul(comp_ctx->builder, left, right, "mul"); + LLVMTypeRef param_types[2]; + param_types[1] = param_types[0] = is_i32 ? I32_TYPE : I64_TYPE; + + LLVMValueRef res; + LLVM_BUILD_OP_OR_INTRINSIC(Mul, left, right, res, + is_i32 ? "i32.mul" : "i64.mul", "mul", false); + + return res; } static bool @@ -679,8 +686,9 @@ compile_op_int_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, "compile int sub fail."); return true; case INT_MUL: - DEF_INT_BINARY_OP(compile_int_mul(comp_ctx, left, right, is_i32), - "compile int mul fail."); + DEF_INT_BINARY_OP( + compile_int_mul(comp_ctx, func_ctx, left, right, is_i32), + "compile int mul fail."); return true; case INT_DIV_S: case INT_DIV_U: @@ -726,43 +734,57 @@ fail: } static LLVMValueRef -compile_int_shl(AOTCompContext *comp_ctx, LLVMValueRef left, LLVMValueRef right, - bool is_i32) +compile_int_shl(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + LLVMValueRef left, LLVMValueRef right, bool is_i32) { LLVMValueRef res; SHIFT_COUNT_MASK; /* Build shl */ - LLVM_BUILD_OP(Shl, left, right, res, "shl", NULL); + LLVMTypeRef param_types[2]; + param_types[1] = param_types[0] = is_i32 ? I32_TYPE : I64_TYPE; + + LLVM_BUILD_OP_OR_INTRINSIC(Shl, left, right, res, + is_i32 ? "i32.shl" : "i64.shl", "shl", false); return res; } static LLVMValueRef -compile_int_shr_s(AOTCompContext *comp_ctx, LLVMValueRef left, - LLVMValueRef right, bool is_i32) +compile_int_shr_s(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + LLVMValueRef left, LLVMValueRef right, bool is_i32) { LLVMValueRef res; SHIFT_COUNT_MASK; /* Build shl */ - LLVM_BUILD_OP(AShr, left, right, res, "shr_s", NULL); + LLVMTypeRef param_types[2]; + param_types[1] = param_types[0] = is_i32 ? I32_TYPE : I64_TYPE; + + LLVM_BUILD_OP_OR_INTRINSIC(AShr, left, right, res, + is_i32 ? "i32.shr_s" : "i64.shr_s", "shr_s", + false); return res; } static LLVMValueRef -compile_int_shr_u(AOTCompContext *comp_ctx, LLVMValueRef left, - LLVMValueRef right, bool is_i32) +compile_int_shr_u(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, + LLVMValueRef left, LLVMValueRef right, bool is_i32) { LLVMValueRef res; SHIFT_COUNT_MASK; /* Build shl */ - LLVM_BUILD_OP(LShr, left, right, res, "shr_u", NULL); + LLVMTypeRef param_types[2]; + param_types[1] = param_types[0] = is_i32 ? I32_TYPE : I64_TYPE; + + LLVM_BUILD_OP_OR_INTRINSIC(LShr, left, right, res, + is_i32 ? "i32.shr_u" : "i64.shr_u", "shr_u", + false); return res; } @@ -814,16 +836,18 @@ compile_op_int_shift(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, { switch (shift_op) { case INT_SHL: - DEF_INT_BINARY_OP(compile_int_shl(comp_ctx, left, right, is_i32), - NULL); + DEF_INT_BINARY_OP( + compile_int_shl(comp_ctx, func_ctx, left, right, is_i32), NULL); return true; case INT_SHR_S: - DEF_INT_BINARY_OP(compile_int_shr_s(comp_ctx, left, right, is_i32), - NULL); + DEF_INT_BINARY_OP( + compile_int_shr_s(comp_ctx, func_ctx, left, right, is_i32), + NULL); return true; case INT_SHR_U: - DEF_INT_BINARY_OP(compile_int_shr_u(comp_ctx, left, right, is_i32), - NULL); + DEF_INT_BINARY_OP( + compile_int_shr_u(comp_ctx, func_ctx, left, right, is_i32), + NULL); return true; case INT_ROTL: DEF_INT_BINARY_OP(