mirror of
https://github.com/odin-lang/Odin.git
synced 2026-04-18 12:30:28 +00:00
Add intrinsics.simd_pairwise_(add|sub)
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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},
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user