소스 검색

Merge pull request #4466 from Barinzaya/simd_extract_msbs

SIMD Extract MSbs/LSbs Intrinsics
gingerBill 6 달 전
부모
커밋
0781526b35
5개의 변경된 파일73개의 추가작업 그리고 0개의 파일을 삭제
  1. 3 0
      base/intrinsics/intrinsics.odin
  2. 3 0
      core/simd/simd.odin
  3. 33 0
      src/check_builtin.cpp
  4. 6 0
      src/checker_builtin_procs.hpp
  5. 28 0
      src/llvm_backend_proc.cpp

+ 3 - 0
base/intrinsics/intrinsics.odin

@@ -285,6 +285,9 @@ 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..<N] where type_is_integer(T) || type_is_boolean(T) ---
+simd_extract_msbs       :: proc(a: #simd[N]T) -> bit_set[0..<N] where type_is_integer(T) || type_is_boolean(T) ---
+
 
 simd_gather       :: proc(ptr: #simd[N]rawptr, val: #simd[N]T, mask: #simd[N]U) -> #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) ---

+ 3 - 0
core/simd/simd.odin

@@ -135,6 +135,9 @@ reduce_xor         :: intrinsics.simd_reduce_xor
 reduce_any         :: intrinsics.simd_reduce_any
 reduce_all         :: intrinsics.simd_reduce_all
 
+extract_lsbs       :: intrinsics.simd_extract_lsbs
+extract_msbs       :: intrinsics.simd_extract_msbs
+
 // swizzle :: proc(a: #simd[N]T, indices: ..int) -> #simd[len(indices)]T
 swizzle :: builtin.swizzle
 

+ 33 - 0
src/check_builtin.cpp

@@ -888,6 +888,39 @@ 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 = {};
+			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:
 		{

+ 6 - 0
src/checker_builtin_procs.hpp

@@ -181,6 +181,9 @@ BuiltinProc__simd_begin,
 	BuiltinProc_simd_reduce_any,
 	BuiltinProc_simd_reduce_all,
 
+	BuiltinProc_simd_extract_lsbs,
+	BuiltinProc_simd_extract_msbs,
+
 	BuiltinProc_simd_shuffle,
 	BuiltinProc_simd_select,
 
@@ -523,6 +526,9 @@ 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},
+
 
 	{STR_LIT("simd_shuffle"), 2, true,  Expr_Expr, BuiltinProcPkg_intrinsics},
 	{STR_LIT("simd_select"),  3, false, Expr_Expr, BuiltinProcPkg_intrinsics},

+ 28 - 0
src/llvm_backend_proc.cpp

@@ -1564,6 +1564,34 @@ 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;
+			GB_ASSERT(vt->kind == Type_SimdVector);
+
+			i64 elem_bits = 8*type_size_of(elem);
+			i64 num_elems = get_array_type_count(vt);
+
+			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, "");
+
+			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:
 		{