diff options
| author | gingerBill <bill@gingerbill.org> | 2022-05-26 11:02:02 +0100 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2022-05-26 11:02:02 +0100 |
| commit | 0fd43c1a0b697ea919efdeef42427694f32692bf (patch) | |
| tree | 58512075dc550dc40483660c3fc6365b6269f115 /src | |
| parent | 06337129d8de636ad00e8ea64218d48c67514611 (diff) | |
Add simd.{sqrt, ceil, floor, trunc, nearest}
Diffstat (limited to 'src')
| -rw-r--r-- | src/check_builtin.cpp | 26 | ||||
| -rw-r--r-- | src/check_type.cpp | 7 | ||||
| -rw-r--r-- | src/checker_builtin_procs.hpp | 12 | ||||
| -rw-r--r-- | src/llvm_backend_proc.cpp | 30 | ||||
| -rw-r--r-- | src/types.cpp | 3 |
5 files changed, 73 insertions, 5 deletions
diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 40933fcaa..74c28f4d2 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -886,6 +886,32 @@ bool check_builtin_simd_operation(CheckerContext *c, Operand *operand, Ast *call return true; } + case BuiltinProc_simd_sqrt: + case BuiltinProc_simd_ceil: + case BuiltinProc_simd_floor: + case BuiltinProc_simd_trunc: + case BuiltinProc_simd_nearest: + { + Operand x = {}; + check_expr(c, &x, ce->args[0]); if (x.mode == Addressing_Invalid) { return false; } + + if (!is_type_simd_vector(x.type)) { + error(x.expr, "'%.*s' expected a simd vector boolean type", LIT(builtin_name)); + return false; + } + Type *elem = base_array_type(x.type); + if (!is_type_float(elem)) { + gbString x_str = type_to_string(x.type); + error(x.expr, "'%.*s' expected a simd vector floating point type, got '%s'", LIT(builtin_name), x_str); + gb_string_free(x_str); + return false; + } + + operand->mode = Addressing_Value; + operand->type = x.type; + return true; + } + default: GB_PANIC("Unhandled simd intrinsic: %.*s", LIT(builtin_name)); diff --git a/src/check_type.cpp b/src/check_type.cpp index 74fa235d5..de58db054 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -2797,7 +2797,7 @@ bool check_type_internal(CheckerContext *ctx, Ast *e, Type **type, Type *named_t } else if (name == "simd") { if (!is_type_valid_vector_elem(elem) && !is_type_polymorphic(elem)) { gbString str = type_to_string(elem); - error(at->elem, "Invalid element type for 'intrinsics.simd_vector', expected an integer, float, or boolean with no specific endianness, got '%s'", str); + error(at->elem, "Invalid element type for #simd, expected an integer, float, or boolean with no specific endianness, got '%s'", str); gb_string_free(str); *type = alloc_type_array(elem, count, generic_type); goto array_end; @@ -2806,7 +2806,7 @@ bool check_type_internal(CheckerContext *ctx, Ast *e, Type **type, Type *named_t if (is_type_polymorphic(elem)) { // Ignore } else if (count < 1 || !is_power_of_two(count)) { - error(at->count, "Invalid length for 'intrinsics.simd_vector', expected a power of two length, got '%lld'", cast(long long)count); + error(at->count, "Invalid length for #simd, expected a power of two length, got '%lld'", cast(long long)count); *type = alloc_type_array(elem, count, generic_type); goto array_end; } else @@ -2817,6 +2817,9 @@ bool check_type_internal(CheckerContext *ctx, Ast *e, Type **type, Type *named_t error(at->count, "wasm based targets are limited to 128-bit types"); } } + if (count > SIMD_ELEMENT_COUNT_MAX) { + error(at->count, "#simd support a maximum element count of %d, got %lld", SIMD_ELEMENT_COUNT_MAX, cast(long long)count); + } } else { error(at->tag, "Invalid tag applied to array, got #%.*s", LIT(name)); *type = alloc_type_array(elem, count, generic_type); diff --git a/src/checker_builtin_procs.hpp b/src/checker_builtin_procs.hpp index 0fff70f01..adb4e4624 100644 --- a/src/checker_builtin_procs.hpp +++ b/src/checker_builtin_procs.hpp @@ -159,6 +159,12 @@ BuiltinProc__simd_begin, BuiltinProc_simd_shuffle, BuiltinProc_simd_select, + + BuiltinProc_simd_sqrt, + BuiltinProc_simd_ceil, + BuiltinProc_simd_floor, + BuiltinProc_simd_trunc, + BuiltinProc_simd_nearest, BuiltinProc__simd_end, // Platform specific intrinsics @@ -421,6 +427,12 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = { {STR_LIT("simd_shuffle"), 2, true, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("simd_select"), 3, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + + {STR_LIT("simd_sqrt") , 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("simd_ceil") , 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("simd_floor"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("simd_trunc"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("simd_nearest"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT(""), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics}, diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index 05477d84b..88129ba5d 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -1231,9 +1231,7 @@ lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAndValue const GB_ASSERT_MSG(id != 0, "Unable to find %s.%s", name, LLVMPrintTypeToString(types[0])); LLVMValueRef ip = LLVMGetIntrinsicDeclaration(p->module->mod, id, types, gb_count_of(types)); - lbValue res = {}; res.value = LLVMBuildCall(p->builder, ip, args, cast(unsigned)args_count, ""); - res.type = tv.type; return res; } case BuiltinProc_simd_reduce_min: @@ -1274,7 +1272,6 @@ lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAndValue const LLVMValueRef args[1] = {}; args[0] = arg0.value; - lbValue res = {}; res.value = LLVMBuildCall(p->builder, ip, args, gb_count_of(args), ""); return res; } @@ -1314,6 +1311,33 @@ lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAndValue const return res; } + case BuiltinProc_simd_sqrt: + case BuiltinProc_simd_ceil: + case BuiltinProc_simd_floor: + case BuiltinProc_simd_trunc: + case BuiltinProc_simd_nearest: + { + char const *name = nullptr; + switch (builtin_id) { + case BuiltinProc_simd_sqrt: name = "llvm.sqrt"; break; + case BuiltinProc_simd_ceil: name = "llvm.ceil"; break; + case BuiltinProc_simd_floor: name = "llvm.floor"; break; + case BuiltinProc_simd_trunc: name = "llvm.trunc"; break; + case BuiltinProc_simd_nearest: name = "llvm.nearbyint"; break; + } + + LLVMTypeRef types[1] = {lb_type(p->module, arg0.type)}; + unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name)); + GB_ASSERT_MSG(id != 0, "Unable to find %s.%s", name, LLVMPrintTypeToString(types[0])); + LLVMValueRef ip = LLVMGetIntrinsicDeclaration(p->module->mod, id, types, gb_count_of(types)); + + LLVMValueRef args[1] = {}; + args[0] = arg0.value; + + res.value = LLVMBuildCall(p->builder, ip, args, gb_count_of(args), ""); + return res; + } + } GB_PANIC("Unhandled simd intrinsic: '%.*s'", LIT(builtin_procs[builtin_id].name)); diff --git a/src/types.cpp b/src/types.cpp index 4fca25e52..fccea2937 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -363,6 +363,9 @@ enum : int { MATRIX_ELEMENT_COUNT_MIN = 1, MATRIX_ELEMENT_COUNT_MAX = 16, MATRIX_ELEMENT_MAX_SIZE = MATRIX_ELEMENT_COUNT_MAX * (2 * 8), // complex128 + + SIMD_ELEMENT_COUNT_MIN = 1, + SIMD_ELEMENT_COUNT_MAX = 64, }; |