mirror of
https://github.com/odin-lang/Odin.git
synced 2026-04-19 13:00:28 +00:00
intrinsics.to_bits_signed; simd.signbit
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
// This is purely for documentation
|
||||
7// This is purely for documentation
|
||||
#+build ignore
|
||||
package intrinsics
|
||||
|
||||
@@ -351,7 +351,8 @@ simd_nearest :: proc(a: #simd[N]any_float) -> #simd[N]any_float ---
|
||||
simd_approx_recip :: proc(x: #simd[N]T) -> #simd[N]T where type_is_float(T)) ---
|
||||
simd_approx_recip_sqrt :: proc(x: #simd[N]T) -> #simd[N]T where type_is_float(T)) ---
|
||||
|
||||
simd_to_bits :: proc(v: #simd[N]T) -> #simd[N]Integer where size_of(T) == size_of(Integer), type_is_unsigned(Integer) ---
|
||||
simd_to_bits :: proc(v: #simd[N]T) -> #simd[N]Integer where size_of(T) == size_of(Integer), type_is_unsigned(Integer) ---
|
||||
simd_to_bits_signed :: proc(v: #simd[N]T) -> #simd[N]Integer where size_of(T) == size_of(Integer), !type_is_unsigned(Integer) ---
|
||||
|
||||
// equivalent to a swizzle with descending indices, e.g. reserve(a, 3, 2, 1, 0)
|
||||
simd_lanes_reverse :: proc(a: #simd[N]T) -> #simd[N]T ---
|
||||
|
||||
@@ -2517,10 +2517,16 @@ Compute the nearest integer of each lane in a SIMD vector.
|
||||
nearest :: intrinsics.simd_nearest
|
||||
|
||||
/*
|
||||
Transmute a SIMD vector into an integer vector.
|
||||
Transmute a SIMD vector into an unsigned integer vector.
|
||||
*/
|
||||
to_bits :: intrinsics.simd_to_bits
|
||||
|
||||
/*
|
||||
Transmute a SIMD vector into a signed integer vector.
|
||||
*/
|
||||
to_bits_signed :: intrinsics.simd_to_bits_signed
|
||||
|
||||
|
||||
/*
|
||||
Reverse the lanes of a SIMD vector.
|
||||
|
||||
@@ -2779,6 +2785,15 @@ signum :: #force_inline proc "contextless" (v: $T/#simd[$LANES]$E) -> T where in
|
||||
return select(is_nan, v, copysign(T(1), v))
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
signbit :: #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))
|
||||
masked := bit_and(val, mask)
|
||||
return to_bits(shr(to_bits_signed(masked), BITS-1))
|
||||
}
|
||||
|
||||
/*
|
||||
Calculate reciprocals of SIMD lanes.
|
||||
|
||||
@@ -2848,7 +2863,6 @@ iota :: intrinsics.simd_indices
|
||||
sums_of_n :: intrinsics.simd_sums_of_n
|
||||
|
||||
|
||||
|
||||
@(require_results)
|
||||
saturating_neg :: #force_inline proc "contextless" (v: $T/#simd[$LANES]$E) -> T where intrinsics.type_is_integer(E) {
|
||||
return saturating_sub(T(0), v)
|
||||
|
||||
@@ -887,14 +887,24 @@ gb_internal bool check_builtin_simd_operation(CheckerContext *c, Operand *operan
|
||||
Operand x = {};
|
||||
Operand y = {};
|
||||
check_expr(c, &x, ce->args[0]); if (x.mode == Addressing_Invalid) return false;
|
||||
check_expr_with_type_hint(c, &y, ce->args[1], x.type); if (y.mode == Addressing_Invalid) return false;
|
||||
convert_to_typed(c, &y, x.type); if (y.mode == Addressing_Invalid) return false;
|
||||
check_expr(c, &y, ce->args[1]); if (y.mode == Addressing_Invalid) return false;
|
||||
if (!is_type_simd_vector(x.type)) {
|
||||
error(x.expr, "'%.*s' expected a simd vector type", LIT(builtin_name));
|
||||
return false;
|
||||
}
|
||||
if (!is_type_simd_vector(y.type)) {
|
||||
error(y.expr, "'%.*s' expected a simd vector type", LIT(builtin_name));
|
||||
if (is_type_untyped(y.type) || is_type_unsigned(y.type)) {
|
||||
Type *rhs_type = type_unsigned_equivalent(x.type);
|
||||
convert_to_typed(c, &y, rhs_type); if (y.mode == Addressing_Invalid) return false;
|
||||
} else {
|
||||
convert_to_typed(c, &y, x.type); if (y.mode == Addressing_Invalid) return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_type_simd_vector(y.type)) {
|
||||
gbString s = type_to_string(y.type);
|
||||
error(y.expr, "'%.*s' expected a simd vector type or unsigned integer, got %s", LIT(builtin_name), s);
|
||||
gb_string_free(s);
|
||||
return false;
|
||||
}
|
||||
GB_ASSERT(x.type->kind == Type_SimdVector);
|
||||
@@ -1706,15 +1716,25 @@ gb_internal bool check_builtin_simd_operation(CheckerContext *c, Operand *operan
|
||||
}
|
||||
Type *elem = base_array_type(x.type);
|
||||
i64 count = get_array_type_count(x.type);
|
||||
i64 sz = type_size_of(elem);
|
||||
Type *bit_elem = nullptr;
|
||||
switch (sz) {
|
||||
case 1: bit_elem = t_u8; break;
|
||||
case 2: bit_elem = t_u16; break;
|
||||
case 4: bit_elem = t_u32; break;
|
||||
case 8: bit_elem = t_u64; break;
|
||||
Type *bit_elem = type_unsigned_equivalent(elem);
|
||||
|
||||
operand->type = alloc_type_simd_vector(count, bit_elem);
|
||||
operand->mode = Addressing_Value;
|
||||
return true;
|
||||
}
|
||||
|
||||
case BuiltinProc_simd_to_bits_signed:
|
||||
{
|
||||
Operand x = {};
|
||||
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 type", LIT(builtin_name));
|
||||
return false;
|
||||
}
|
||||
GB_ASSERT(bit_elem != nullptr);
|
||||
Type *elem = base_array_type(x.type);
|
||||
i64 count = get_array_type_count(x.type);
|
||||
Type *bit_elem = type_signed_equivalent(elem);
|
||||
|
||||
operand->type = alloc_type_simd_vector(count, bit_elem);
|
||||
operand->mode = Addressing_Value;
|
||||
|
||||
@@ -217,6 +217,7 @@ BuiltinProc__simd_begin,
|
||||
BuiltinProc_simd_approx_recip_sqrt,
|
||||
|
||||
BuiltinProc_simd_to_bits,
|
||||
BuiltinProc_simd_to_bits_signed,
|
||||
|
||||
BuiltinProc_simd_lanes_reverse,
|
||||
BuiltinProc_simd_lanes_rotate_left,
|
||||
@@ -614,6 +615,7 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
|
||||
{STR_LIT("simd_approx_recip_sqrt"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
|
||||
{STR_LIT("simd_to_bits"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("simd_to_bits_signed"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
|
||||
{STR_LIT("simd_lanes_reverse"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("simd_lanes_rotate_left"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
|
||||
@@ -2500,6 +2500,7 @@ gb_internal lbValue lb_build_builtin_simd_proc(lbProcedure *p, Ast *expr, TypeAn
|
||||
}
|
||||
|
||||
case BuiltinProc_simd_to_bits:
|
||||
case BuiltinProc_simd_to_bits_signed:
|
||||
{
|
||||
res.value = LLVMBuildBitCast(p->builder, arg0.value, lb_type(m, tv.type), "");
|
||||
return res;
|
||||
|
||||
@@ -1332,6 +1332,8 @@ gb_internal bool is_type_integer_or_float(Type *t) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
gb_internal bool is_type_numeric(Type *t) {
|
||||
t = base_type(t);
|
||||
if (t == nullptr) { return false; }
|
||||
@@ -1709,6 +1711,51 @@ gb_internal bool is_type_simd_vector(Type *t) {
|
||||
return t->kind == Type_SimdVector;
|
||||
}
|
||||
|
||||
|
||||
gb_internal Type *type_unsigned_equivalent(Type *t) {
|
||||
Type *original_type = t;
|
||||
t = base_type(t);
|
||||
if (is_type_simd_vector(t)) {
|
||||
if (is_type_unsigned(t->SimdVector.elem)) {
|
||||
return original_type;
|
||||
}
|
||||
return alloc_type_simd_vector(t->SimdVector.count, type_unsigned_equivalent(t->SimdVector.elem));
|
||||
}
|
||||
|
||||
i64 sz = type_size_of(t);
|
||||
switch (sz) {
|
||||
case 1: return t_u8;
|
||||
case 2: return t_u16;
|
||||
case 4: return t_u32;
|
||||
case 8: return t_u64;
|
||||
case 16: return t_u128;
|
||||
}
|
||||
GB_PANIC("No known equivalent unsigned integer sized for %s", type_to_string(t));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
gb_internal Type *type_signed_equivalent(Type *t) {
|
||||
Type *original_type = t;
|
||||
t = base_type(t);
|
||||
if (is_type_simd_vector(t)) {
|
||||
if (!is_type_unsigned(t->SimdVector.elem)) {
|
||||
return original_type;
|
||||
}
|
||||
return alloc_type_simd_vector(t->SimdVector.count, type_signed_equivalent(t->SimdVector.elem));
|
||||
}
|
||||
;
|
||||
i64 sz = type_size_of(t);
|
||||
switch (sz) {
|
||||
case 1: return t_i8;
|
||||
case 2: return t_i16;
|
||||
case 4: return t_i32;
|
||||
case 8: return t_i64;
|
||||
case 16: return t_i128;
|
||||
}
|
||||
GB_PANIC("No known equivalent signed integer sized for %s", type_to_string(t));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
gb_internal Type *base_array_type(Type *t) {
|
||||
Type *bt = base_type(t);
|
||||
if (is_type_array(bt)) {
|
||||
|
||||
Reference in New Issue
Block a user