Fix missing float cmp for XIP (#1699)

This commit is contained in:
Huang Qi 2022-11-14 11:58:38 +08:00 committed by GitHub
parent cef4e74fee
commit 4b0660cf24
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 68 additions and 6 deletions

View File

@ -72,6 +72,8 @@ static const aot_intrinsic g_intrinsic_mapping[] = {
{ "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},
{ "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},
};
/* clang-format on */
@ -524,6 +526,18 @@ aot_intrinsic_i64_rem_u(uint64 l, uint64 r)
return l % r;
}
uint64
aot_intrinsic_i64_bit_or(uint64 l, uint64 r)
{
return l | r;
}
uint64
aot_intrinsic_i64_bit_and(uint64 l, uint64 r)
{
return l & r;
}
const char *
aot_intrinsic_get_symbol(const char *llvm_intrinsic)
{
@ -558,6 +572,8 @@ add_i64_common_intrinsics(AOTCompContext *comp_ctx)
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);
add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I64_BIT_OR);
add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_I64_BIT_AND);
}
static void

View File

@ -93,6 +93,8 @@ extern "C" {
#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)
#define AOT_INTRINSIC_FLAG_I64_BIT_OR AOT_INTRINSIC_FLAG(1, 32)
#define AOT_INTRINSIC_FLAG_I64_BIT_AND AOT_INTRINSIC_FLAG(1, 33)
/* clang-format on */
@ -267,6 +269,12 @@ aot_intrinsic_i64_rem_s(int64 l, int64 r);
uint64
aot_intrinsic_i64_rem_u(uint64 l, uint64 r);
uint64
aot_intrinsic_i64_bit_or(uint64 l, uint64 r);
uint64
aot_intrinsic_i64_bit_and(uint64 l, uint64 r);
const char *
aot_intrinsic_get_symbol(const char *llvm_intrinsic);

View File

@ -112,6 +112,8 @@ typedef struct {
REG_SYM(aot_intrinsic_i64_div_u), \
REG_SYM(aot_intrinsic_i64_rem_s), \
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_i32_div_u), \
#define REG_COMMON_SYMBOLS \

View File

@ -234,15 +234,49 @@ 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;
if (!(is_nan = LLVMBuildFCmp(comp_ctx->builder, LLVMRealUNO, left, right,
"is_nan"))
|| !(is_eq = LLVMBuildFCmp(comp_ctx->builder, LLVMRealOEQ, left, right,
"is_eq"))) {
if (comp_ctx->disable_llvm_intrinsics
&& aot_intrinsic_check_capability(comp_ctx,
is_f32 ? "f32_cmp" : "f64_cmp")) {
LLVMTypeRef param_types[3];
LLVMValueRef opcond = LLVMConstInt(I32_TYPE, FLOAT_UNO, true);
param_types[0] = I32_TYPE;
param_types[1] = is_f32 ? F32_TYPE : F64_TYPE;
param_types[2] = param_types[1];
is_nan = aot_call_llvm_intrinsic(
comp_ctx, func_ctx, is_f32 ? "f32_cmp" : "f64_cmp", I32_TYPE,
param_types, 3, opcond, left, right);
opcond = LLVMConstInt(I32_TYPE, FLOAT_EQ, true);
is_eq = aot_call_llvm_intrinsic(
comp_ctx, func_ctx, is_f32 ? "f32_cmp" : "f64_cmp", I32_TYPE,
param_types, 3, opcond, left, right);
if (!is_nan || !is_eq) {
return NULL;
}
if (!(is_nan = LLVMBuildIntCast(comp_ctx->builder, is_nan, INT1_TYPE,
"bit_cast_is_nan"))) {
aot_set_last_error("llvm build is_nan bit cast fail.");
return NULL;
}
if (!(is_eq = LLVMBuildIntCast(comp_ctx->builder, is_eq, INT1_TYPE,
"bit_cast_is_eq"))) {
aot_set_last_error("llvm build is_eq bit cast fail.");
return NULL;
}
}
else if (!(is_nan = LLVMBuildFCmp(comp_ctx->builder, LLVMRealUNO, left,
right, "is_nan"))
|| !(is_eq = LLVMBuildFCmp(comp_ctx->builder, LLVMRealOEQ, left,
right, "is_eq"))) {
aot_set_last_error("llvm build fcmp fail.");
return NULL;
}
@ -258,9 +292,11 @@ compile_op_float_min_max(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
}
if (is_min)
LLVM_BUILD_OP(Or, left_int, right_int, tmp, "tmp_int", NULL);
LLVM_BUILD_OP_OR_INTRINSIC(Or, left_int, right_int, tmp, "i64.or",
"tmp_int", false);
else
LLVM_BUILD_OP(And, left_int, right_int, tmp, "tmp_int", NULL);
LLVM_BUILD_OP_OR_INTRINSIC(And, left_int, right_int, tmp, "i64.and",
"tmp_int", false);
if (!(tmp = LLVMBuildBitCast(comp_ctx->builder, tmp, ret_type, "tmp"))) {
aot_set_last_error("llvm build bitcast fail.");