authorgravatar for daniele.cocca@gmail.comDaniele Cocca <daniele.cocca@gmail.com> 2022-03-14 14:10:52+00:00
committergravatar for daniele.cocca@gmail.comDaniele Cocca <daniele.cocca@gmail.com> 2022-03-14 19:43:31+00:00
log8643591c9a42d07508c9b5b623d606f27f26af2c
treeecbcf8f99e2d675c974dad84a68d776000a21ec5
parentd912699e0853e8fe1a9dd2c863f3c163d123c407

CBE: split {clz,ctz,mod,popCount,byteSwap,bitReverse} by type

This also surfaces the fact that clz, ctz and popCount didn't actually support 128 bit integers, despite what was claimed by 226fcd7c709ec664c5d883042cf7beb3026f66cb. This was partially hidden by the fact that the test code for popCount only exercised 128 bit integers in a comptime context. This commit duplicates that test case for runtime ints too.

4 files changed, 249 insertions(+), 105 deletions(-)

src/codegen/c.zig+14-17
...@@ -1709,11 +1709,11 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO...@@ -1709,11 +1709,11 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
1709 .memcpy => try airMemcpy(f, inst),1709 .memcpy => try airMemcpy(f, inst),
1710 .set_union_tag => try airSetUnionTag(f, inst),1710 .set_union_tag => try airSetUnionTag(f, inst),
1711 .get_union_tag => try airGetUnionTag(f, inst),1711 .get_union_tag => try airGetUnionTag(f, inst),
1712 .clz => try airBuiltinCall(f, inst, "clz", .{}),1712 .clz => try airBuiltinCall(f, inst, "clz"),
1713 .ctz => try airBuiltinCall(f, inst, "ctz", .{}),1713 .ctz => try airBuiltinCall(f, inst, "ctz"),
1714 .popcount => try airBuiltinCall(f, inst, "popcount", .{}),1714 .popcount => try airBuiltinCall(f, inst, "popcount"),
1715 .byte_swap => try airBuiltinCall(f, inst, "byte_swap", .{ .needs_signedness_info = true }),1715 .byte_swap => try airBuiltinCall(f, inst, "byte_swap"),
1716 .bit_reverse => try airBuiltinCall(f, inst, "bit_reverse", .{ .needs_signedness_info = true }),1716 .bit_reverse => try airBuiltinCall(f, inst, "bit_reverse"),
1717 .tag_name => try airTagName(f, inst),1717 .tag_name => try airTagName(f, inst),
1718 .error_name => try airErrorName(f, inst),1718 .error_name => try airErrorName(f, inst),
1719 .splat => try airSplat(f, inst),1719 .splat => try airSplat(f, inst),
...@@ -3351,7 +3351,7 @@ fn airPtrToInt(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3351,7 +3351,7 @@ fn airPtrToInt(f: *Function, inst: Air.Inst.Index) !CValue {
3351 return local;3351 return local;
3352}3352}
33533353
3354fn airBuiltinCall(f: *Function, inst: Air.Inst.Index, fn_name: [*:0]const u8, options: struct { needs_signedness_info: bool = false }) !CValue {3354fn airBuiltinCall(f: *Function, inst: Air.Inst.Index, fn_name: [*:0]const u8) !CValue {
3355 if (f.liveness.isUnused(inst)) return CValue.none;3355 if (f.liveness.isUnused(inst)) return CValue.none;
33563356
3357 const inst_ty = f.air.typeOfIndex(inst);3357 const inst_ty = f.air.typeOfIndex(inst);
...@@ -3362,20 +3362,17 @@ fn airBuiltinCall(f: *Function, inst: Air.Inst.Index, fn_name: [*:0]const u8, op...@@ -3362,20 +3362,17 @@ fn airBuiltinCall(f: *Function, inst: Air.Inst.Index, fn_name: [*:0]const u8, op
3362 const writer = f.object.writer();3362 const writer = f.object.writer();
33633363
3364 const int_info = operand_ty.intInfo(target);3364 const int_info = operand_ty.intInfo(target);
3365 _ = toCIntBits(int_info.bits) orelse3365 const c_bits = toCIntBits(int_info.bits) orelse
3366 return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{});3366 return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{});
33673367
3368 try writer.print(" = zig_{s}(", .{fn_name});3368 try writer.print(" = zig_{s}_", .{fn_name});
3369 const prefix_byte: u8 = switch (int_info.signedness) {
3370 .signed => 'i',
3371 .unsigned => 'u',
3372 };
3373 try writer.print("{c}{d}(", .{ prefix_byte, c_bits });
3369 try f.writeCValue(writer, try f.resolveInst(operand));3374 try f.writeCValue(writer, try f.resolveInst(operand));
3370 try writer.print(", {d}", .{int_info.bits});3375 try writer.print(", {d});\n", .{int_info.bits});
3371 if (options.needs_signedness_info) {
3372 const signed_type = switch (int_info.signedness) {
3373 .signed => "true",
3374 .unsigned => "false",
3375 };
3376 try writer.print(", {s}", .{signed_type});
3377 }
3378 try writer.writeAll(");\n");
3379 return local;3376 return local;
3380}3377}
33813378
src/link/C/zig.h+231-87
...@@ -503,104 +503,248 @@ zig_shl_sat_s(long, long, ((sizeof(long )) * CHAR_BIT - 1))...@@ -503,104 +503,248 @@ zig_shl_sat_s(long, long, ((sizeof(long )) * CHAR_BIT - 1))
503503
504#define zig_bitsizeof(T) (CHAR_BIT * sizeof(T))504#define zig_bitsizeof(T) (CHAR_BIT * sizeof(T))
505#define zig_bit_mask(T, bit_width) \505#define zig_bit_mask(T, bit_width) \
506 ((bit_width) == 128 \506 ((bit_width) == zig_bitsizeof(T) \
507 ? ((T)(((uint128_t) 0xffffffffffffffff) << 64 | \507 ? ((T)-1) \
508 (uint128_t) 0xffffffffffffffff)) \
509 : (((T)1 << (T)(bit_width)) - 1))508 : (((T)1 << (T)(bit_width)) - 1))
510509
511static inline uint128_t zig_sign_extend(uint128_t value, uint128_t zig_type_bit_width) {510static inline int zig_clz(unsigned int value, uint8_t zig_type_bit_width) {
512 const uint128_t m = (uint128_t)1 << (zig_type_bit_width - 1);511 if (value == 0) return zig_type_bit_width;
513 return (value ^ m) - m;512 return __builtin_clz(value) - zig_bitsizeof(unsigned int) + zig_type_bit_width;
513}
514
515static inline int zig_clzl(unsigned long value, uint8_t zig_type_bit_width) {
516 if (value == 0) return zig_type_bit_width;
517 return __builtin_clzl(value) - zig_bitsizeof(unsigned long) + zig_type_bit_width;
518}
519
520static inline int zig_clzll(unsigned long long value, uint8_t zig_type_bit_width) {
521 if (value == 0) return zig_type_bit_width;
522 return __builtin_clzll(value) - zig_bitsizeof(unsigned long long) + zig_type_bit_width;
523}
524
525#define zig_clz_u8 zig_clz
526#define zig_clz_i8 zig_clz
527#define zig_clz_u16 zig_clz
528#define zig_clz_i16 zig_clz
529#define zig_clz_u32 zig_clzl
530#define zig_clz_i32 zig_clzl
531#define zig_clz_u64 zig_clzll
532#define zig_clz_i64 zig_clzll
533
534static inline int zig_clz_u128(uint128_t value, uint8_t zig_type_bit_width) {
535 if (value == 0) return zig_type_bit_width;
536 const uint128_t mask = zig_bit_mask(uint128_t, zig_type_bit_width);
537 const uint64_t hi = (value & mask) >> 64;
538 const uint64_t lo = (value & mask);
539 const int leading_zeroes = (
540 hi != 0 ? __builtin_clzll(hi) : 64 + (lo != 0 ? __builtin_clzll(lo) : 64));
541 return leading_zeroes - zig_bitsizeof(uint128_t) + zig_type_bit_width;
542}
543
544#define zig_clz_i128 zig_clz_u128
545
546static inline int zig_ctz(unsigned int value, uint8_t zig_type_bit_width) {
547 if (value == 0) return zig_type_bit_width;
548 return __builtin_ctz(value & zig_bit_mask(unsigned int, zig_type_bit_width));
514}549}
515550
516static inline int zig_clz(unsigned long long value, uint8_t zig_type_bit_width) {551static inline int zig_ctzl(unsigned long value, uint8_t zig_type_bit_width) {
517 if (value == 0) return zig_type_bit_width;552 if (value == 0) return zig_type_bit_width;
518 if (zig_type_bit_width <= zig_bitsizeof(unsigned int))553 return __builtin_ctzl(value & zig_bit_mask(unsigned long, zig_type_bit_width));
519 return (__builtin_clz(value) - zig_bitsizeof(unsigned int) + zig_type_bit_width);
520 if (zig_type_bit_width <= zig_bitsizeof(unsigned long))
521 return (__builtin_clzl(value) - zig_bitsizeof(unsigned long) + zig_type_bit_width);
522 return (__builtin_clzll(value) - zig_bitsizeof(unsigned long long) + zig_type_bit_width);
523}554}
524555
525static inline int zig_ctz(unsigned long long value, uint8_t zig_type_bit_width) {556static inline int zig_ctzll(unsigned long value, uint8_t zig_type_bit_width) {
526 if (value == 0) return zig_type_bit_width;557 if (value == 0) return zig_type_bit_width;
527 if (zig_type_bit_width <= zig_bitsizeof(unsigned int)) return __builtin_ctz(value);558 return __builtin_ctzll(value & zig_bit_mask(unsigned long, zig_type_bit_width));
528 if (zig_type_bit_width <= zig_bitsizeof(unsigned long)) return __builtin_ctzl(value);559}
529 return __builtin_ctzll(value);560
530}561#define zig_ctz_u8 zig_ctz
531562#define zig_ctz_i8 zig_ctz
532static inline int zig_popcount(unsigned long long value, uint8_t zig_type_bit_width) {563#define zig_ctz_u16 zig_ctz
533 const unsigned long long mask = zig_bit_mask(unsigned long long, zig_type_bit_width);564#define zig_ctz_i16 zig_ctz
534 if (zig_type_bit_width <= zig_bitsizeof(unsigned int))565#define zig_ctz_u32 zig_ctzl
535 return __builtin_popcount(value & mask);566#define zig_ctz_i32 zig_ctzl
536 if (zig_type_bit_width <= zig_bitsizeof(unsigned long))567#define zig_ctz_u64 zig_ctzll
537 return __builtin_popcountl(value & mask);568#define zig_ctz_i64 zig_ctzll
538 return __builtin_popcountll(value & mask);569
539}570static inline int zig_ctz_u128(uint128_t value, uint8_t zig_type_bit_width) {
540571 const uint128_t mask = zig_bit_mask(uint128_t, zig_type_bit_width);
541static inline uint128_t zig_byte_swap(uint128_t value, uint8_t zig_type_bit_width, bool signed_type) {572 const uint64_t hi = (value & mask) >> 64;
542 if (zig_type_bit_width <= 8) return value;573 const uint64_t lo = (value & mask);
543 if (zig_type_bit_width <= 16) return __builtin_bswap16(value);574 return (lo != 0 ? __builtin_ctzll(lo) : 64 + (hi != 0 ? __builtin_ctzll(hi) : 64));
544 if (zig_type_bit_width <= 32) {575}
545 const uint32_t swapped = __builtin_bswap32(value) >> (32 - zig_type_bit_width);576
546 return (signed_type ? zig_sign_extend(swapped, zig_type_bit_width) : swapped);577#define zig_ctz_i128 zig_ctz_u128
578
579static inline int zig_popcount(unsigned int value, uint8_t zig_type_bit_width) {
580 return __builtin_popcount(value & zig_bit_mask(unsigned int, zig_type_bit_width));
581}
582
583static inline int zig_popcountl(unsigned long value, uint8_t zig_type_bit_width) {
584 return __builtin_popcountl(value & zig_bit_mask(unsigned long, zig_type_bit_width));
585}
586
587static inline int zig_popcountll(unsigned long value, uint8_t zig_type_bit_width) {
588 return __builtin_popcountll(value & zig_bit_mask(unsigned long, zig_type_bit_width));
589}
590
591#define zig_popcount_u8 zig_popcount
592#define zig_popcount_i8 zig_popcount
593#define zig_popcount_u16 zig_popcount
594#define zig_popcount_i16 zig_popcount
595#define zig_popcount_u32 zig_popcountl
596#define zig_popcount_i32 zig_popcountl
597#define zig_popcount_u64 zig_popcountll
598#define zig_popcount_i64 zig_popcountll
599
600static inline int zig_popcount_u128(uint128_t value, uint8_t zig_type_bit_width) {
601 const uint128_t mask = zig_bit_mask(uint128_t, zig_type_bit_width);
602 const uint64_t hi = (value & mask) >> 64;
603 const uint64_t lo = (value & mask);
604 return __builtin_popcountll(hi) + __builtin_popcountll(lo);
605}
606
607#define zig_popcount_i128 zig_popcount_u128
608
609#define zig_sign_extend(T) \
610 static inline T zig_sign_extend_##T(T value, uint8_t zig_type_bit_width) { \
611 const T m = (T)1 << (T)(zig_type_bit_width - 1); \
612 return (value ^ m) - m; \
547 }613 }
548 if (zig_type_bit_width <= 64) {614
549 const uint64_t swapped = __builtin_bswap64(value) >> (64 - zig_type_bit_width);615zig_sign_extend(uint8_t)
550 return (signed_type ? zig_sign_extend(swapped, zig_type_bit_width) : swapped);616zig_sign_extend(uint16_t)
617zig_sign_extend(uint32_t)
618zig_sign_extend(uint64_t)
619zig_sign_extend(uint128_t)
620
621#define zig_byte_swap_u(ZigTypeBits, CTypeBits) \
622 static inline uint##CTypeBits##_t zig_byte_swap_u##ZigTypeBits(uint##CTypeBits##_t value, uint8_t zig_type_bit_width) { \
623 return __builtin_bswap##CTypeBits(value) >> (CTypeBits - zig_type_bit_width); \
624 }
625
626#define zig_byte_swap_s(ZigTypeBits, CTypeBits) \
627 static inline int##CTypeBits##_t zig_byte_swap_i##ZigTypeBits(int##CTypeBits##_t value, uint8_t zig_type_bit_width) { \
628 const uint##CTypeBits##_t swapped = zig_byte_swap_u##ZigTypeBits(value, zig_type_bit_width); \
629 return zig_sign_extend_uint##CTypeBits##_t(swapped, zig_type_bit_width); \
551 }630 }
631
632#define zig_byte_swap(ZigTypeBits, CTypeBits) \
633 zig_byte_swap_u(ZigTypeBits, CTypeBits) \
634 zig_byte_swap_s(ZigTypeBits, CTypeBits)
635
636zig_byte_swap( 8, 16)
637zig_byte_swap(16, 16)
638zig_byte_swap(32, 32)
639zig_byte_swap(64, 64)
640
641static inline uint128_t zig_byte_swap_u128(uint128_t value, uint8_t zig_type_bit_width) {
552 const uint128_t mask = zig_bit_mask(uint128_t, zig_type_bit_width);642 const uint128_t mask = zig_bit_mask(uint128_t, zig_type_bit_width);
553 const uint128_t hi = __builtin_bswap64((uint64_t)(value >> 64));643 const uint128_t hi = __builtin_bswap64((uint64_t)(value >> 64));
554 const uint128_t lo = __builtin_bswap64((uint64_t)value);644 const uint128_t lo = __builtin_bswap64((uint64_t)value);
555 const uint128_t swapped = (((lo << 64 | hi) >> (128 - zig_type_bit_width))) & mask;645 return (((lo << 64 | hi) >> (128 - zig_type_bit_width))) & mask;
556 return (signed_type ? zig_sign_extend(swapped, zig_type_bit_width) : swapped);646}
557}647
558648zig_byte_swap_s(128, 128)
559static inline uint128_t zig_bit_reverse(uint128_t value, uint8_t zig_type_bit_width, bool signed_type) {649
560 static const uint128_t reverse_lut[256] = {650static const uint8_t zig_bit_reverse_lut[256] = {
561 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0,651 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0,
562 0x30, 0xb0, 0x70, 0xf0, 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,652 0x30, 0xb0, 0x70, 0xf0, 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
563 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 0x04, 0x84, 0x44, 0xc4,653 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 0x04, 0x84, 0x44, 0xc4,
564 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,654 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
565 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc,655 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc,
566 0x3c, 0xbc, 0x7c, 0xfc, 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,656 0x3c, 0xbc, 0x7c, 0xfc, 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
567 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 0x0a, 0x8a, 0x4a, 0xca,657 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 0x0a, 0x8a, 0x4a, 0xca,
568 0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,658 0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
569 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6,659 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6,
570 0x36, 0xb6, 0x76, 0xf6, 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,660 0x36, 0xb6, 0x76, 0xf6, 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
571 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 0x01, 0x81, 0x41, 0xc1,661 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 0x01, 0x81, 0x41, 0xc1,
572 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,662 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
573 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9,663 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9,
574 0x39, 0xb9, 0x79, 0xf9, 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,664 0x39, 0xb9, 0x79, 0xf9, 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
575 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 0x0d, 0x8d, 0x4d, 0xcd,665 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 0x0d, 0x8d, 0x4d, 0xcd,
576 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,666 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
577 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3,667 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3,
578 0x33, 0xb3, 0x73, 0xf3, 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,668 0x33, 0xb3, 0x73, 0xf3, 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
579 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 0x07, 0x87, 0x47, 0xc7,669 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 0x07, 0x87, 0x47, 0xc7,
580 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,670 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
581 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf,671 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf,
582 0x3f, 0xbf, 0x7f, 0xff672 0x3f, 0xbf, 0x7f, 0xff
583 };673};
584 const uint128_t mask = zig_bit_mask(uint128_t, zig_type_bit_width);674
585 const uint128_t swapped = zig_byte_swap(value, zig_type_bit_width, signed_type);675static inline uint8_t zig_bit_reverse_u8(uint8_t value, uint8_t zig_type_bit_width) {
676 const uint8_t reversed = zig_bit_reverse_lut[value] >> (8 - zig_type_bit_width);
677 return zig_sign_extend_uint8_t(reversed, zig_type_bit_width);
678}
679
680#define zig_bit_reverse_i8 zig_bit_reverse_u8
681
682static inline uint16_t zig_bit_reverse_u16(uint16_t value, uint8_t zig_type_bit_width) {
683 const uint16_t swapped = zig_byte_swap_u16(value, zig_type_bit_width);
684 const uint16_t reversed = (
685 ((uint16_t)zig_bit_reverse_lut[(swapped >> 0x08) & 0xff] << 0x08) |
686 ((uint16_t)zig_bit_reverse_lut[(swapped >> 0x00) & 0xff] << 0x00));
687 return zig_sign_extend_uint16_t(
688 reversed & zig_bit_mask(uint16_t, zig_type_bit_width),
689 zig_type_bit_width);
690}
691
692#define zig_bit_reverse_i16 zig_bit_reverse_u16
693
694static inline uint32_t zig_bit_reverse_u32(uint32_t value, uint8_t zig_type_bit_width) {
695 const uint32_t swapped = zig_byte_swap_u32(value, zig_type_bit_width);
696 const uint32_t reversed = (
697 ((uint32_t)zig_bit_reverse_lut[(swapped >> 0x18) & 0xff] << 0x18) |
698 ((uint32_t)zig_bit_reverse_lut[(swapped >> 0x10) & 0xff] << 0x10) |
699 ((uint32_t)zig_bit_reverse_lut[(swapped >> 0x08) & 0xff] << 0x08) |
700 ((uint32_t)zig_bit_reverse_lut[(swapped >> 0x00) & 0xff] << 0x00));
701 return zig_sign_extend_uint32_t(
702 reversed & zig_bit_mask(uint32_t, zig_type_bit_width),
703 zig_type_bit_width);
704}
705
706#define zig_bit_reverse_i32 zig_bit_reverse_u32
707
708static inline uint64_t zig_bit_reverse_u64(uint64_t value, uint8_t zig_type_bit_width) {
709 const uint64_t swapped = zig_byte_swap_u64(value, zig_type_bit_width);
710 const uint64_t reversed = (
711 ((uint64_t)zig_bit_reverse_lut[(swapped >> 0x38) & 0xff] << 0x38) |
712 ((uint64_t)zig_bit_reverse_lut[(swapped >> 0x30) & 0xff] << 0x30) |
713 ((uint64_t)zig_bit_reverse_lut[(swapped >> 0x28) & 0xff] << 0x28) |
714 ((uint64_t)zig_bit_reverse_lut[(swapped >> 0x20) & 0xff] << 0x20) |
715 ((uint64_t)zig_bit_reverse_lut[(swapped >> 0x18) & 0xff] << 0x18) |
716 ((uint64_t)zig_bit_reverse_lut[(swapped >> 0x10) & 0xff] << 0x10) |
717 ((uint64_t)zig_bit_reverse_lut[(swapped >> 0x08) & 0xff] << 0x08) |
718 ((uint64_t)zig_bit_reverse_lut[(swapped >> 0x00) & 0xff] << 0x00));
719 return zig_sign_extend_uint64_t(
720 reversed & zig_bit_mask(uint64_t, zig_type_bit_width),
721 zig_type_bit_width);
722}
723
724#define zig_bit_reverse_i64 zig_bit_reverse_u64
725
726static inline uint128_t zig_bit_reverse_u128(uint128_t value, uint8_t zig_type_bit_width) {
727 const uint128_t swapped = zig_byte_swap_u128(value, zig_type_bit_width);
586 const uint128_t reversed = (728 const uint128_t reversed = (
587 (reverse_lut[(swapped >> 0x78) & 0xff] << 0x78) |729 ((uint128_t)zig_bit_reverse_lut[(swapped >> 0x78) & 0xff] << 0x78) |
588 (reverse_lut[(swapped >> 0x70) & 0xff] << 0x70) |730 ((uint128_t)zig_bit_reverse_lut[(swapped >> 0x70) & 0xff] << 0x70) |
589 (reverse_lut[(swapped >> 0x68) & 0xff] << 0x68) |731 ((uint128_t)zig_bit_reverse_lut[(swapped >> 0x68) & 0xff] << 0x68) |
590 (reverse_lut[(swapped >> 0x60) & 0xff] << 0x60) |732 ((uint128_t)zig_bit_reverse_lut[(swapped >> 0x60) & 0xff] << 0x60) |
591 (reverse_lut[(swapped >> 0x58) & 0xff] << 0x58) |733 ((uint128_t)zig_bit_reverse_lut[(swapped >> 0x58) & 0xff] << 0x58) |
592 (reverse_lut[(swapped >> 0x50) & 0xff] << 0x50) |734 ((uint128_t)zig_bit_reverse_lut[(swapped >> 0x50) & 0xff] << 0x50) |
593 (reverse_lut[(swapped >> 0x48) & 0xff] << 0x48) |735 ((uint128_t)zig_bit_reverse_lut[(swapped >> 0x48) & 0xff] << 0x48) |
594 (reverse_lut[(swapped >> 0x40) & 0xff] << 0x40) |736 ((uint128_t)zig_bit_reverse_lut[(swapped >> 0x40) & 0xff] << 0x40) |
595 (reverse_lut[(swapped >> 0x38) & 0xff] << 0x38) |737 ((uint128_t)zig_bit_reverse_lut[(swapped >> 0x38) & 0xff] << 0x38) |
596 (reverse_lut[(swapped >> 0x30) & 0xff] << 0x30) |738 ((uint128_t)zig_bit_reverse_lut[(swapped >> 0x30) & 0xff] << 0x30) |
597 (reverse_lut[(swapped >> 0x28) & 0xff] << 0x28) |739 ((uint128_t)zig_bit_reverse_lut[(swapped >> 0x28) & 0xff] << 0x28) |
598 (reverse_lut[(swapped >> 0x20) & 0xff] << 0x20) |740 ((uint128_t)zig_bit_reverse_lut[(swapped >> 0x20) & 0xff] << 0x20) |
599 (reverse_lut[(swapped >> 0x18) & 0xff] << 0x18) |741 ((uint128_t)zig_bit_reverse_lut[(swapped >> 0x18) & 0xff] << 0x18) |
600 (reverse_lut[(swapped >> 0x10) & 0xff] << 0x10) |742 ((uint128_t)zig_bit_reverse_lut[(swapped >> 0x10) & 0xff] << 0x10) |
601 (reverse_lut[(swapped >> 0x08) & 0xff] << 0x08) |743 ((uint128_t)zig_bit_reverse_lut[(swapped >> 0x08) & 0xff] << 0x08) |
602 (reverse_lut[(swapped >> 0x00) & 0xff] << 0x00));744 ((uint128_t)zig_bit_reverse_lut[(swapped >> 0x00) & 0xff] << 0x00));
603 const uint128_t result =745 return zig_sign_extend_uint128_t(
604 (reversed >> (zig_type_bit_width < 8 ? 8 - zig_type_bit_width : 0)) & mask;746 reversed & zig_bit_mask(uint128_t, zig_type_bit_width),
605 return (signed_type ? zig_sign_extend(result, zig_type_bit_width) : result);747 zig_type_bit_width);
606}748}
749
750#define zig_bit_reverse_i128 zig_bit_reverse_u128
test/behavior/math.zig-1
...@@ -82,7 +82,6 @@ test "@clz big ints" {...@@ -82,7 +82,6 @@ test "@clz big ints" {
82 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO82 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
83 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO83 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
84 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO84 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
85 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
8685
87 try testClzBigInts();86 try testClzBigInts();
88 comptime try testClzBigInts();87 comptime try testClzBigInts();
test/behavior/popcount.zig+4
...@@ -37,6 +37,10 @@ fn testPopCountIntegers() !void {...@@ -37,6 +37,10 @@ fn testPopCountIntegers() !void {
37 var x: i8 = -120;37 var x: i8 = -120;
38 try expect(@popCount(i8, x) == 2);38 try expect(@popCount(i8, x) == 2);
39 }39 }
40 {
41 var x: u128 = 0b11111111000110001100010000100001000011000011100101010001;
42 try expect(@popCount(u128, x) == 24);
43 }
40 comptime {44 comptime {
41 try expect(@popCount(u8, @bitCast(u8, @as(i8, -120))) == 2);45 try expect(@popCount(u8, @bitCast(u8, @as(i8, -120))) == 2);
42 }46 }