mirror of
https://github.com/odin-lang/Odin.git
synced 2026-01-09 14:32:41 +00:00
Support count_ones etc with #simd
This commit is contained in:
@@ -22,10 +22,10 @@ alloca :: proc(size, align: int) -> [^]u8 ---
|
||||
cpu_relax :: proc() ---
|
||||
read_cycle_counter :: proc() -> i64 ---
|
||||
|
||||
count_ones :: proc(x: $T) -> T where type_is_integer(T) ---
|
||||
count_zeros :: proc(x: $T) -> T where type_is_integer(T) ---
|
||||
count_trailing_zeros :: proc(x: $T) -> T where type_is_integer(T) ---
|
||||
count_leading_zeros :: proc(x: $T) -> T where type_is_integer(T) ---
|
||||
count_ones :: proc(x: $T) -> T where type_is_integer(T) || type_is_simd_vector(T) ---
|
||||
count_zeros :: proc(x: $T) -> T where type_is_integer(T) || type_is_simd_vector(T) ---
|
||||
count_trailing_zeros :: proc(x: $T) -> T where type_is_integer(T) || type_is_simd_vector(T) ---
|
||||
count_leading_zeros :: proc(x: $T) -> T where type_is_integer(T) || type_is_simd_vector(T) ---
|
||||
reverse_bits :: proc(x: $T) -> T where type_is_integer(T) ---
|
||||
byte_swap :: proc(x: $T) -> T where type_is_integer(T) || type_is_float(T) ---
|
||||
|
||||
|
||||
@@ -104,6 +104,11 @@ reverse :: intrinsics.simd_reverse
|
||||
rotate_left :: intrinsics.simd_rotate_left
|
||||
rotate_right :: intrinsics.simd_rotate_right
|
||||
|
||||
count_ones :: intrinsics.count_ones
|
||||
count_zeros :: intrinsics.count_zeros
|
||||
count_trailing_zeros :: intrinsics.count_trailing_zeros
|
||||
count_leading_zeros :: intrinsics.count_leading_zeros
|
||||
|
||||
to_array_ptr :: #force_inline proc "contextless" (v: ^#simd[$LANES]$E) -> ^[LANES]E {
|
||||
return (^[LANES]E)(v)
|
||||
}
|
||||
@@ -129,16 +134,16 @@ bit_not :: #force_inline proc "contextless" (v: $T/#simd[$LANES]$E) -> T where i
|
||||
|
||||
copysign :: #force_inline proc "contextless" (v, sign: $T/#simd[$LANES]$E) -> T where intrinsics.type_is_float(E) {
|
||||
neg_zero := to_bits(T(-0.0))
|
||||
sign_bit := and(to_bits(sign), neg_zero)
|
||||
magnitude := and(to_bits(v), bit_not(neg_zero))
|
||||
return transmute(T)or(sign_bit, magnitude)
|
||||
sign_bit := to_bits(sign) & neg_zero
|
||||
magnitude := to_bits(v) &~ neg_zero
|
||||
return transmute(T)(sign_bit|magnitude)
|
||||
}
|
||||
|
||||
signum :: #force_inline proc "contextless" (v: $T/#simd[$LANES]$E) -> T where intrinsics.type_is_float(E) {
|
||||
is_nan := ne(v, v)
|
||||
is_nan := lanes_ne(v, v)
|
||||
return select(is_nan, v, copysign(T(1), v))
|
||||
}
|
||||
|
||||
recip :: #force_inline proc "contextless" (v: $T/#simd[$LANES]$E) -> T where intrinsics.type_is_float(E) {
|
||||
return div(T(1), v)
|
||||
return T(1) / v
|
||||
}
|
||||
|
||||
@@ -3559,7 +3559,14 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!is_type_integer_like(x.type)) {
|
||||
if (is_type_simd_vector(x.type) && id != BuiltinProc_reverse_bits) {
|
||||
Type *elem = base_array_type(x.type);
|
||||
if (!is_type_integer_like(elem)) {
|
||||
gbString xts = type_to_string(x.type);
|
||||
error(x.expr, "#simd values passed to '%.*s' must have an element of an integer-like type (integer, boolean, enum, bit_set), got %s", LIT(builtin_name), xts);
|
||||
gb_string_free(xts);
|
||||
}
|
||||
} else if (!is_type_integer_like(x.type)) {
|
||||
gbString xts = type_to_string(x.type);
|
||||
error(x.expr, "Values passed to '%.*s' must be an integer-like type (integer, boolean, enum, bit_set), got %s", LIT(builtin_name), xts);
|
||||
gb_string_free(xts);
|
||||
|
||||
@@ -485,8 +485,10 @@ lbValue lb_emit_count_ones(lbProcedure *p, lbValue x, Type *type) {
|
||||
}
|
||||
|
||||
lbValue lb_emit_count_zeros(lbProcedure *p, lbValue x, Type *type) {
|
||||
i64 sz = 8*type_size_of(type);
|
||||
lbValue size = lb_const_int(p->module, type, cast(u64)sz);
|
||||
Type *elem = base_array_type(type);
|
||||
i64 sz = 8*type_size_of(elem);
|
||||
lbValue size = lb_const_int(p->module, elem, cast(u64)sz);
|
||||
size = lb_emit_conv(p, size, type);
|
||||
lbValue count = lb_emit_count_ones(p, x, type);
|
||||
return lb_emit_arith(p, Token_Sub, size, count, type);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user