From 33a3aab7914fbed9abb0abfa696590ae25d03f4f Mon Sep 17 00:00:00 2001 From: Barinzaya Date: Tue, 15 Oct 2024 18:13:35 -0400 Subject: [PATCH 1/2] Added simd_extract_msbs intrinsic. --- base/intrinsics/intrinsics.odin | 2 ++ core/simd/simd.odin | 2 ++ src/check_builtin.cpp | 32 ++++++++++++++++++++++++++++++++ src/checker_builtin_procs.hpp | 4 ++++ src/llvm_backend_proc.cpp | 24 ++++++++++++++++++++++++ 5 files changed, 64 insertions(+) diff --git a/base/intrinsics/intrinsics.odin b/base/intrinsics/intrinsics.odin index ee0d357e4..64fc08a30 100644 --- a/base/intrinsics/intrinsics.odin +++ b/base/intrinsics/intrinsics.odin @@ -285,6 +285,8 @@ simd_reduce_xor :: proc(a: #simd[N]T) -> T where type_is_integer(T) || 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_extract_msbs :: proc(a: #simd[N]T) -> bit_set[0.. #simd[N]T where type_is_integer(U) || type_is_boolean(U) --- simd_scatter :: proc(ptr: #simd[N]rawptr, val: #simd[N]T, mask: #simd[N]U) where type_is_integer(U) || type_is_boolean(U) --- diff --git a/core/simd/simd.odin b/core/simd/simd.odin index 01d11dfbe..517cef656 100644 --- a/core/simd/simd.odin +++ b/core/simd/simd.odin @@ -135,6 +135,8 @@ reduce_xor :: intrinsics.simd_reduce_xor reduce_any :: intrinsics.simd_reduce_any reduce_all :: intrinsics.simd_reduce_all +extract_msbs :: intrinsics.simd_extract_msbs + // 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 5aa4cf027..12124096f 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -888,6 +888,38 @@ gb_internal bool check_builtin_simd_operation(CheckerContext *c, Operand *operan return true; } + case BuiltinProc_simd_extract_msbs: + { + Operand x = {}; + check_expr(c, &x, ce->args[0]); if (x.mode == Addressing_Invalid) return false; + + if (!is_type_simd_vector(x.type)) { + gbString xs = type_to_string(x.type); + error(x.expr, "'%.*s' expected a simd vector type, got '%s'", LIT(builtin_name), xs); + gb_string_free(xs); + return false; + } + + Type *elem = base_array_type(x.type); + if (!is_type_integer_like(elem)) { + gbString xs = type_to_string(x.type); + error(x.expr, "'%.*s' expected a #simd type with integer or boolean elements, got '%s'", LIT(builtin_name), xs); + gb_string_free(xs); + return false; + } + + i64 num_elems = get_array_type_count(x.type); + + Type *result_type = alloc_type_bit_set(); + result_type->BitSet.elem = t_int; + result_type->BitSet.lower = 0; + result_type->BitSet.upper = num_elems - 1; + + operand->mode = Addressing_Value; + operand->type = result_type; + return true; + } + case BuiltinProc_simd_shuffle: { diff --git a/src/checker_builtin_procs.hpp b/src/checker_builtin_procs.hpp index 2dfd570e4..92f9f1602 100644 --- a/src/checker_builtin_procs.hpp +++ b/src/checker_builtin_procs.hpp @@ -181,6 +181,8 @@ BuiltinProc__simd_begin, BuiltinProc_simd_reduce_any, BuiltinProc_simd_reduce_all, + BuiltinProc_simd_extract_msbs, + BuiltinProc_simd_shuffle, BuiltinProc_simd_select, @@ -523,6 +525,8 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = { {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_extract_msbs"), 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 e5c04852c..eea0fe03e 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -1564,6 +1564,30 @@ gb_internal lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAn return res; } + case BuiltinProc_simd_extract_msbs: + { + Type *vt = arg0.type; + GB_ASSERT(vt->kind == Type_SimdVector); + + i64 elem_bits = 8*type_size_of(elem); + i64 num_elems = get_array_type_count(vt); + + LLVMTypeRef word_type = lb_type(m, elem); + LLVMValueRef shift_value = llvm_splat_int(num_elems, word_type, elem_bits - 1); + LLVMValueRef broadcast_value = LLVMBuildAShr(p->builder, arg0.value, shift_value, ""); + + LLVMTypeRef bitvec_type = LLVMVectorType(LLVMInt1TypeInContext(m->ctx), (unsigned)num_elems); + LLVMValueRef bitvec_value = LLVMBuildTrunc(p->builder, broadcast_value, bitvec_type, ""); + + LLVMTypeRef mask_type = LLVMIntTypeInContext(m->ctx, (unsigned)num_elems); + LLVMValueRef mask_value = LLVMBuildBitCast(p->builder, bitvec_value, mask_type, ""); + + LLVMTypeRef result_type = lb_type(m, res.type); + res.value = LLVMBuildZExtOrBitCast(p->builder, mask_value, result_type, ""); + + return res; + } + case BuiltinProc_simd_shuffle: { From 4afedbc051e92647c9003d33b1a231330fe3b025 Mon Sep 17 00:00:00 2001 From: Barinzaya Date: Mon, 24 Feb 2025 08:49:57 -0500 Subject: [PATCH 2/2] Added simd_extract_lsbs intrinsic as well. Equivalent to the simd_extract_msbs intrinsic, except it extracts the least significant bit of each element instead. --- base/intrinsics/intrinsics.odin | 1 + core/simd/simd.odin | 1 + src/check_builtin.cpp | 1 + src/checker_builtin_procs.hpp | 2 ++ src/llvm_backend_proc.cpp | 10 +++++++--- 5 files changed, 12 insertions(+), 3 deletions(-) diff --git a/base/intrinsics/intrinsics.odin b/base/intrinsics/intrinsics.odin index 64fc08a30..bec452007 100644 --- a/base/intrinsics/intrinsics.odin +++ b/base/intrinsics/intrinsics.odin @@ -285,6 +285,7 @@ simd_reduce_xor :: proc(a: #simd[N]T) -> T where type_is_integer(T) || 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_extract_lsbs :: proc(a: #simd[N]T) -> bit_set[0.. bit_set[0.. #simd[len(indices)]T diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 12124096f..023aeff73 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -888,6 +888,7 @@ gb_internal bool check_builtin_simd_operation(CheckerContext *c, Operand *operan return true; } + case BuiltinProc_simd_extract_lsbs: case BuiltinProc_simd_extract_msbs: { Operand x = {}; diff --git a/src/checker_builtin_procs.hpp b/src/checker_builtin_procs.hpp index 92f9f1602..40dde8240 100644 --- a/src/checker_builtin_procs.hpp +++ b/src/checker_builtin_procs.hpp @@ -181,6 +181,7 @@ BuiltinProc__simd_begin, BuiltinProc_simd_reduce_any, BuiltinProc_simd_reduce_all, + BuiltinProc_simd_extract_lsbs, BuiltinProc_simd_extract_msbs, BuiltinProc_simd_shuffle, @@ -525,6 +526,7 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = { {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_extract_lsbs"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("simd_extract_msbs"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index eea0fe03e..b41f4723c 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -1564,6 +1564,7 @@ gb_internal lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAn return res; } + case BuiltinProc_simd_extract_lsbs: case BuiltinProc_simd_extract_msbs: { Type *vt = arg0.type; @@ -1572,9 +1573,12 @@ gb_internal lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAn i64 elem_bits = 8*type_size_of(elem); i64 num_elems = get_array_type_count(vt); - LLVMTypeRef word_type = lb_type(m, elem); - LLVMValueRef shift_value = llvm_splat_int(num_elems, word_type, elem_bits - 1); - LLVMValueRef broadcast_value = LLVMBuildAShr(p->builder, arg0.value, shift_value, ""); + LLVMValueRef broadcast_value = arg0.value; + if (builtin_id == BuiltinProc_simd_extract_msbs) { + LLVMTypeRef word_type = lb_type(m, elem); + LLVMValueRef shift_value = llvm_splat_int(num_elems, word_type, elem_bits - 1); + broadcast_value = LLVMBuildAShr(p->builder, broadcast_value, shift_value, ""); + } LLVMTypeRef bitvec_type = LLVMVectorType(LLVMInt1TypeInContext(m->ctx), (unsigned)num_elems); LLVMValueRef bitvec_value = LLVMBuildTrunc(p->builder, broadcast_value, bitvec_type, "");