Add intrinsics.simd_pairwise_(add|sub)

This commit is contained in:
gingerBill
2026-04-07 15:45:50 +01:00
parent 6e09ce9a04
commit 6f7226e692
5 changed files with 52 additions and 2 deletions

View File

@@ -366,6 +366,10 @@ simd_odd_even :: proc(a, b: #simd[N]T) -> #simd[N]T ---
// Returns the sums of N consecutive lanes
simd_sums_of_n :: proc(a: #simd[LANES]T, $N: uint) -> #simd[LANES/N]T where is_power_of_two(N) ---
simd_pairwise_add :: proc(a, b: #simd[LANES]T) -> #simd[LANES/N]T ---
simd_pairwise_sub :: proc(a, b: #simd[LANES]T) -> #simd[LANES/N]T ---
// Checks if the current target supports the given target features.
//
// Takes a constant comma-seperated string (eg: "sha512,sse4.1"), or a procedure type which has either

View File

@@ -2786,7 +2786,7 @@ signum :: #force_inline proc "contextless" (v: $T/#simd[$LANES]$E) -> T where in
}
@(require_results)
signbit :: #force_inline proc "contextless" (v: $T/#simd[$LANES]$E) -> (res: type_of(intrinsics.simd_to_bits(T{}))) {
sign_bit :: #force_inline proc "contextless" (v: $T/#simd[$LANES]$E) -> (res: type_of(intrinsics.simd_to_bits(T{}))) {
BITS :: 8*size_of(E)
val := to_bits(v)
mask := type_of(val)(1<<(BITS-1))
@@ -2877,3 +2877,6 @@ saturating_abs :: #force_inline proc "contextless" (v: $T/#simd[$LANES]$E) -> T
abs_diff :: #force_inline proc "contextless" (a, b: $T/#simd[$LANES]$E) -> T where intrinsics.type_is_integer(E) {
return abs(sub(a, b))
}
pairwise_add :: intrinsics.simd_pairwise_add
pairwise_sub :: intrinsics.simd_pairwise_add

View File

@@ -781,6 +781,8 @@ gb_internal bool check_builtin_simd_operation(CheckerContext *c, Operand *operan
case BuiltinProc_simd_div:
case BuiltinProc_simd_min:
case BuiltinProc_simd_max:
case BuiltinProc_simd_pairwise_add:
case BuiltinProc_simd_pairwise_sub:
{
Operand x = {};
Operand y = {};
@@ -1537,7 +1539,7 @@ gb_internal bool check_builtin_simd_operation(CheckerContext *c, Operand *operan
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));
error(x.expr, "'%.*s' expected a simd vector type", LIT(builtin_name));
return false;
}
Type *bt = base_type(x.type);

View File

@@ -208,6 +208,9 @@ BuiltinProc__simd_begin,
BuiltinProc_simd_sums_of_n,
BuiltinProc_simd_pairwise_add,
BuiltinProc_simd_pairwise_sub,
BuiltinProc_simd_ceil,
BuiltinProc_simd_floor,
BuiltinProc_simd_trunc,
@@ -606,6 +609,9 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
{STR_LIT("simd_sums_of_n"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
{STR_LIT("simd_pairwise_add"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
{STR_LIT("simd_pairwise_sub"), 2, 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},

View File

@@ -2143,6 +2143,41 @@ gb_internal lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAn
} break;
case BuiltinProc_simd_pairwise_add:
case BuiltinProc_simd_pairwise_sub:
if (is_float) {
switch (builtin_id) {
case BuiltinProc_simd_pairwise_add: op_code = LLVMFAdd; break;
case BuiltinProc_simd_pairwise_sub: op_code = LLVMFSub; break;
}
} else {
switch (builtin_id) {
case BuiltinProc_simd_pairwise_add: op_code = LLVMAdd; break;
case BuiltinProc_simd_pairwise_sub: op_code = LLVMSub; break;
}
}
if (op_code) {
LLVMValueRef a = arg0.value;
LLVMValueRef b = arg1.value;
unsigned count = LLVMGetVectorSize(LLVMTypeOf(a));
LLVMValueRef *evens = gb_alloc_array(temporary_allocator(), LLVMValueRef, count);
LLVMValueRef *odds = gb_alloc_array(temporary_allocator(), LLVMValueRef, count);
LLVMTypeRef llvm_u32 = lb_type(m, t_u32);
for (unsigned i = 0; i < count; i++) {
evens[i] = LLVMConstInt(llvm_u32, 2*i, false);
odds[i] = LLVMConstInt(llvm_u32, 2*i + 1, false);
}
LLVMValueRef x = LLVMBuildShuffleVector(p->builder, a, b, LLVMConstVector(evens, count), "");
LLVMValueRef y = LLVMBuildShuffleVector(p->builder, a, b, LLVMConstVector(odds, count), "");
res.value = LLVMBuildBinOp(p->builder, op_code, x, y, "");
return res;
}
break;
case BuiltinProc_simd_ceil:
case BuiltinProc_simd_floor:
case BuiltinProc_simd_trunc: