diff --git a/base/intrinsics/intrinsics.odin b/base/intrinsics/intrinsics.odin index 37a42b904..277eafdf1 100644 --- a/base/intrinsics/intrinsics.odin +++ b/base/intrinsics/intrinsics.odin @@ -268,13 +268,17 @@ simd_lanes_ge :: proc(a, b: #simd[N]T) -> #simd[N]Integer --- simd_extract :: proc(a: #simd[N]T, idx: uint) -> T --- simd_replace :: proc(a: #simd[N]T, idx: uint, elem: T) -> #simd[N]T --- -simd_reduce_add_ordered :: proc(a: #simd[N]T) -> T --- -simd_reduce_mul_ordered :: proc(a: #simd[N]T) -> T --- -simd_reduce_min :: proc(a: #simd[N]T) -> T --- -simd_reduce_max :: proc(a: #simd[N]T) -> T --- -simd_reduce_and :: proc(a: #simd[N]T) -> T --- -simd_reduce_or :: proc(a: #simd[N]T) -> T --- -simd_reduce_xor :: proc(a: #simd[N]T) -> T --- +simd_reduce_add_ordered :: proc(a: #simd[N]T) -> T where type_is_integer(T) || type_is_float(T)--- +simd_reduce_mul_ordered :: proc(a: #simd[N]T) -> T where type_is_integer(T) || type_is_float(T)--- +simd_reduce_min :: proc(a: #simd[N]T) -> T where type_is_integer(T) || type_is_float(T)--- +simd_reduce_max :: proc(a: #simd[N]T) -> T where type_is_integer(T) || type_is_float(T)--- +simd_reduce_and :: proc(a: #simd[N]T) -> T where type_is_integer(T) || type_is_float(T)--- +simd_reduce_or :: proc(a: #simd[N]T) -> T where type_is_integer(T) || type_is_float(T)--- +simd_reduce_xor :: proc(a: #simd[N]T) -> T where type_is_integer(T) || type_is_float(T)--- + +simd_reduce_any :: proc(a: #simd[N]T) -> T where type_is_boolean(T) --- +simd_reduce_all :: proc(a: #simd[N]T) -> T where type_is_boolean(T) --- + simd_shuffle :: proc(a, b: #simd[N]T, indices: ..int) -> #simd[len(indices)]T --- simd_select :: proc(cond: #simd[N]boolean_or_integer, true, false: #simd[N]T) -> #simd[N]T --- diff --git a/core/simd/simd.odin b/core/simd/simd.odin index c5a594df6..6166f703b 100644 --- a/core/simd/simd.odin +++ b/core/simd/simd.odin @@ -115,6 +115,9 @@ reduce_and :: intrinsics.simd_reduce_and reduce_or :: intrinsics.simd_reduce_or reduce_xor :: intrinsics.simd_reduce_xor +reduce_any :: intrinsics.simd_reduce_any +reduce_all :: intrinsics.simd_reduce_all + // swizzle :: proc(a: #simd[N]T, indices: ..int) -> #simd[len(indices)]T swizzle :: builtin.swizzle diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index b96337326..73a90ed62 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -775,6 +775,29 @@ gb_internal bool check_builtin_simd_operation(CheckerContext *c, Operand *operan return true; } + case BuiltinProc_simd_reduce_any: + case BuiltinProc_simd_reduce_all: + { + 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 type", LIT(builtin_name)); + return false; + } + Type *elem = base_array_type(x.type); + if (!is_type_boolean(elem)) { + gbString xs = type_to_string(x.type); + error(x.expr, "'%.*s' expected a #simd type with a boolean element, got '%s'", LIT(builtin_name), xs); + gb_string_free(xs); + return false; + } + + operand->mode = Addressing_Value; + operand->type = t_untyped_bool; + return true; + } + case BuiltinProc_simd_shuffle: { diff --git a/src/checker_builtin_procs.hpp b/src/checker_builtin_procs.hpp index 3a2e1ce22..b6eb326d2 100644 --- a/src/checker_builtin_procs.hpp +++ b/src/checker_builtin_procs.hpp @@ -174,6 +174,9 @@ BuiltinProc__simd_begin, BuiltinProc_simd_reduce_or, BuiltinProc_simd_reduce_xor, + BuiltinProc_simd_reduce_any, + BuiltinProc_simd_reduce_all, + BuiltinProc_simd_shuffle, BuiltinProc_simd_select, @@ -501,6 +504,10 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = { {STR_LIT("simd_reduce_or"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("simd_reduce_xor"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("simd_reduce_any"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("simd_reduce_all"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + + {STR_LIT("simd_shuffle"), 2, true, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("simd_select"), 3, false, Expr_Expr, BuiltinProcPkg_intrinsics}, diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index 2f736ff6c..ee121d6f2 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -1527,6 +1527,23 @@ gb_internal lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAn return res; } + case BuiltinProc_simd_reduce_any: + case BuiltinProc_simd_reduce_all: + { + char const *name = nullptr; + switch (builtin_id) { + case BuiltinProc_simd_reduce_any: name = "llvm.vector.reduce.and"; break; + case BuiltinProc_simd_reduce_all: name = "llvm.vector.reduce.or"; break; + } + + LLVMTypeRef types[1] = { lb_type(p->module, arg0.type) }; + LLVMValueRef args[1] = { arg0.value }; + + res.value = lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types)); + return res; + } + + case BuiltinProc_simd_shuffle: { Type *vt = arg0.type;