| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388 |
- /*
- * Copyright (C) 2019 Intel Corporation. All rights reserved.
- * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- */
- #include "simd_floating_point.h"
- #include "simd_common.h"
- #include "../aot_emit_exception.h"
- #include "../aot_emit_numberic.h"
- #include "../../aot/aot_runtime.h"
- static bool
- simd_v128_float_arith(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
- FloatArithmetic arith_op, LLVMTypeRef vector_type)
- {
- LLVMValueRef lhs, rhs, result = NULL;
- if (!(rhs =
- simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, "rhs"))
- || !(lhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
- "lhs"))) {
- return false;
- }
- switch (arith_op) {
- case FLOAT_ADD:
- result = LLVMBuildFAdd(comp_ctx->builder, lhs, rhs, "sum");
- break;
- case FLOAT_SUB:
- result = LLVMBuildFSub(comp_ctx->builder, lhs, rhs, "difference");
- break;
- case FLOAT_MUL:
- result = LLVMBuildFMul(comp_ctx->builder, lhs, rhs, "product");
- break;
- case FLOAT_DIV:
- result = LLVMBuildFDiv(comp_ctx->builder, lhs, rhs, "quotient");
- break;
- default:
- return false;
- }
- if (!result) {
- HANDLE_FAILURE(
- "LLVMBuildFAdd/LLVMBuildFSub/LLVMBuildFMul/LLVMBuildFDiv");
- return false;
- }
- return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result");
- }
- bool
- aot_compile_simd_f32x4_arith(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
- FloatArithmetic arith_op)
- {
- return simd_v128_float_arith(comp_ctx, func_ctx, arith_op, V128_f32x4_TYPE);
- }
- bool
- aot_compile_simd_f64x2_arith(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
- FloatArithmetic arith_op)
- {
- return simd_v128_float_arith(comp_ctx, func_ctx, arith_op, V128_f64x2_TYPE);
- }
- static bool
- simd_v128_float_neg(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
- LLVMTypeRef vector_type)
- {
- LLVMValueRef vector, result;
- if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
- "vector"))) {
- return false;
- }
- if (!(result = LLVMBuildFNeg(comp_ctx->builder, vector, "neg"))) {
- HANDLE_FAILURE("LLVMBuildFNeg");
- return false;
- }
- return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result");
- }
- bool
- aot_compile_simd_f32x4_neg(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
- {
- return simd_v128_float_neg(comp_ctx, func_ctx, V128_f32x4_TYPE);
- }
- bool
- aot_compile_simd_f64x2_neg(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
- {
- return simd_v128_float_neg(comp_ctx, func_ctx, V128_f64x2_TYPE);
- }
- static bool
- simd_float_intrinsic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
- LLVMTypeRef vector_type, const char *intrinsic)
- {
- LLVMValueRef vector, result;
- LLVMTypeRef param_types[1] = { vector_type };
- if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
- "vector"))) {
- return false;
- }
- if (!(result =
- aot_call_llvm_intrinsic(comp_ctx, func_ctx, intrinsic,
- vector_type, param_types, 1, vector))) {
- HANDLE_FAILURE("LLVMBuildCall");
- return false;
- }
- return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result");
- }
- bool
- aot_compile_simd_f32x4_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
- {
- return simd_float_intrinsic(comp_ctx, func_ctx, V128_f32x4_TYPE,
- "llvm.fabs.v4f32");
- }
- bool
- aot_compile_simd_f64x2_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
- {
- return simd_float_intrinsic(comp_ctx, func_ctx, V128_f64x2_TYPE,
- "llvm.fabs.v2f64");
- }
- bool
- aot_compile_simd_f32x4_round(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
- {
- return simd_float_intrinsic(comp_ctx, func_ctx, V128_f32x4_TYPE,
- "llvm.round.v4f32");
- }
- bool
- aot_compile_simd_f64x2_round(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
- {
- return simd_float_intrinsic(comp_ctx, func_ctx, V128_f64x2_TYPE,
- "llvm.round.v2f64");
- }
- bool
- aot_compile_simd_f32x4_sqrt(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
- {
- return simd_float_intrinsic(comp_ctx, func_ctx, V128_f32x4_TYPE,
- "llvm.sqrt.v4f32");
- }
- bool
- aot_compile_simd_f64x2_sqrt(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
- {
- return simd_float_intrinsic(comp_ctx, func_ctx, V128_f64x2_TYPE,
- "llvm.sqrt.v2f64");
- }
- bool
- aot_compile_simd_f32x4_ceil(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
- {
- return simd_float_intrinsic(comp_ctx, func_ctx, V128_f32x4_TYPE,
- "llvm.ceil.v4f32");
- }
- bool
- aot_compile_simd_f64x2_ceil(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
- {
- return simd_float_intrinsic(comp_ctx, func_ctx, V128_f64x2_TYPE,
- "llvm.ceil.v2f64");
- }
- bool
- aot_compile_simd_f32x4_floor(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
- {
- return simd_float_intrinsic(comp_ctx, func_ctx, V128_f32x4_TYPE,
- "llvm.floor.v4f32");
- }
- bool
- aot_compile_simd_f64x2_floor(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
- {
- return simd_float_intrinsic(comp_ctx, func_ctx, V128_f64x2_TYPE,
- "llvm.floor.v2f64");
- }
- bool
- aot_compile_simd_f32x4_trunc(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
- {
- return simd_float_intrinsic(comp_ctx, func_ctx, V128_f32x4_TYPE,
- "llvm.trunc.v4f32");
- }
- bool
- aot_compile_simd_f64x2_trunc(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
- {
- return simd_float_intrinsic(comp_ctx, func_ctx, V128_f64x2_TYPE,
- "llvm.trunc.v2f64");
- }
- bool
- aot_compile_simd_f32x4_nearest(AOTCompContext *comp_ctx,
- AOTFuncContext *func_ctx)
- {
- return simd_float_intrinsic(comp_ctx, func_ctx, V128_f32x4_TYPE,
- "llvm.rint.v4f32");
- }
- bool
- aot_compile_simd_f64x2_nearest(AOTCompContext *comp_ctx,
- AOTFuncContext *func_ctx)
- {
- return simd_float_intrinsic(comp_ctx, func_ctx, V128_f64x2_TYPE,
- "llvm.rint.v2f64");
- }
- static bool
- simd_float_cmp(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
- FloatArithmetic arith_op, LLVMTypeRef vector_type)
- {
- LLVMValueRef lhs, rhs, result;
- LLVMRealPredicate op = FLOAT_MIN == arith_op ? LLVMRealULT : LLVMRealUGT;
- if (!(rhs =
- simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, "rhs"))
- || !(lhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
- "lhs"))) {
- return false;
- }
- if (!(result = LLVMBuildFCmp(comp_ctx->builder, op, lhs, rhs, "cmp"))) {
- HANDLE_FAILURE("LLVMBuildFCmp");
- return false;
- }
- if (!(result =
- LLVMBuildSelect(comp_ctx->builder, result, lhs, rhs, "select"))) {
- HANDLE_FAILURE("LLVMBuildSelect");
- return false;
- }
- return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result");
- }
- /*TODO: sugggest non-IA platforms check with "llvm.minimum.*" and
- * "llvm.maximum.*" firstly */
- bool
- aot_compile_simd_f32x4_min_max(AOTCompContext *comp_ctx,
- AOTFuncContext *func_ctx, bool run_min)
- {
- return simd_float_cmp(comp_ctx, func_ctx, run_min ? FLOAT_MIN : FLOAT_MAX,
- V128_f32x4_TYPE);
- }
- bool
- aot_compile_simd_f64x2_min_max(AOTCompContext *comp_ctx,
- AOTFuncContext *func_ctx, bool run_min)
- {
- return simd_float_cmp(comp_ctx, func_ctx, run_min ? FLOAT_MIN : FLOAT_MAX,
- V128_f64x2_TYPE);
- }
- static bool
- simd_float_pmin_max(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
- LLVMTypeRef vector_type, const char *intrinsic)
- {
- LLVMValueRef lhs, rhs, result;
- LLVMTypeRef param_types[2];
- param_types[0] = vector_type;
- param_types[1] = vector_type;
- if (!(rhs =
- simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type, "rhs"))
- || !(lhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx, vector_type,
- "lhs"))) {
- return false;
- }
- if (!(result =
- aot_call_llvm_intrinsic(comp_ctx, func_ctx, intrinsic,
- vector_type, param_types, 2, lhs, rhs))) {
- return false;
- }
- return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result");
- }
- bool
- aot_compile_simd_f32x4_pmin_pmax(AOTCompContext *comp_ctx,
- AOTFuncContext *func_ctx, bool run_min)
- {
- return simd_float_pmin_max(comp_ctx, func_ctx, V128_f32x4_TYPE,
- run_min ? "llvm.minnum.v4f32"
- : "llvm.maxnum.v4f32");
- }
- bool
- aot_compile_simd_f64x2_pmin_pmax(AOTCompContext *comp_ctx,
- AOTFuncContext *func_ctx, bool run_min)
- {
- return simd_float_pmin_max(comp_ctx, func_ctx, V128_f64x2_TYPE,
- run_min ? "llvm.minnum.v2f64"
- : "llvm.maxnum.v2f64");
- }
- bool
- aot_compile_simd_f64x2_demote(AOTCompContext *comp_ctx,
- AOTFuncContext *func_ctx)
- {
- LLVMValueRef vector, elem_0, elem_1, result;
- if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx,
- V128_f64x2_TYPE, "vector"))) {
- return false;
- }
- if (!(elem_0 = LLVMBuildExtractElement(comp_ctx->builder, vector,
- LLVM_CONST(i32_zero), "elem_0"))
- || !(elem_1 = LLVMBuildExtractElement(comp_ctx->builder, vector,
- LLVM_CONST(i32_one), "elem_1"))) {
- HANDLE_FAILURE("LLVMBuildExtractElement");
- return false;
- }
- /* fptrunc <f64> elem to <f32> */
- if (!(elem_0 = LLVMBuildFPTrunc(comp_ctx->builder, elem_0, F32_TYPE,
- "elem_0_trunc"))
- || !(elem_1 = LLVMBuildFPTrunc(comp_ctx->builder, elem_1, F32_TYPE,
- "elem_1_trunc"))) {
- HANDLE_FAILURE("LLVMBuildFPTrunc");
- return false;
- }
- if (!(result = LLVMBuildInsertElement(comp_ctx->builder,
- LLVM_CONST(f32x4_vec_zero), elem_0,
- LLVM_CONST(i32_zero), "new_vector_0"))
- || !(result =
- LLVMBuildInsertElement(comp_ctx->builder, result, elem_1,
- LLVM_CONST(i32_one), "new_vector_1"))) {
- HANDLE_FAILURE("LLVMBuildInsertElement");
- return false;
- }
- return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result");
- }
- bool
- aot_compile_simd_f32x4_promote(AOTCompContext *comp_ctx,
- AOTFuncContext *func_ctx)
- {
- LLVMValueRef vector, elem_0, elem_1, result;
- if (!(vector = simd_pop_v128_and_bitcast(comp_ctx, func_ctx,
- V128_f32x4_TYPE, "vector"))) {
- return false;
- }
- if (!(elem_0 = LLVMBuildExtractElement(comp_ctx->builder, vector,
- LLVM_CONST(i32_zero), "elem_0"))
- || !(elem_1 = LLVMBuildExtractElement(comp_ctx->builder, vector,
- LLVM_CONST(i32_one), "elem_1"))) {
- HANDLE_FAILURE("LLVMBuildExtractElement");
- return false;
- }
- /* fpext <f32> elem to <f64> */
- if (!(elem_0 =
- LLVMBuildFPExt(comp_ctx->builder, elem_0, F64_TYPE, "elem_0_ext"))
- || !(elem_1 = LLVMBuildFPExt(comp_ctx->builder, elem_1, F64_TYPE,
- "elem_1_ext"))) {
- HANDLE_FAILURE("LLVMBuildFPExt");
- return false;
- }
- if (!(result = LLVMBuildInsertElement(comp_ctx->builder,
- LLVM_CONST(f64x2_vec_zero), elem_0,
- LLVM_CONST(i32_zero), "new_vector_0"))
- || !(result =
- LLVMBuildInsertElement(comp_ctx->builder, result, elem_1,
- LLVM_CONST(i32_one), "new_vector_1"))) {
- HANDLE_FAILURE("LLVMBuildInsertElement");
- return false;
- }
- return simd_bitcast_and_push_v128(comp_ctx, func_ctx, result, "result");
- }
|