| ... | ... | @@ -649,8 +649,73 @@ inline fn negXi2(comptime T: type, a: T) T { |
| 649 | 649 | return -a; |
| 650 | 650 | } |
| 651 | 651 | |
| 652 | | pub fn memset(dest: ?[*]u8, c: c_int, len: usize) callconv(.c) ?[*]u8 { |
| 653 | | @setRuntimeSafety(false); |
| 652 | fn memsetSmallPowerOf2(d: [*]u8, b: u8, comptime size: usize) void { |
| 653 | if (size > @sizeOf(usize)) { |
| 654 | d[0..size].* = @splat(b); |
| 655 | } else { |
| 656 | const T = @Int(.unsigned, 8 * size); |
| 657 | var splatted: T = 0; // Setting this to undefined causes a memset call and thus infinite recursion in Debug test-compiler-rt. |
| 658 | @as(*[size]u8, @ptrCast(&splatted)).* = @splat(b); |
| 659 | @as(*align(1) T, @ptrCast(d)).* = splatted; |
| 660 | } |
| 661 | } |
| 662 | |
| 663 | fn shortMemset( |
| 664 | log_min: comptime_int, |
| 665 | log_max: comptime_int, |
| 666 | d: [*]u8, |
| 667 | b: u8, |
| 668 | len: usize, |
| 669 | ) void { |
| 670 | if (log_min + 1 != log_max) { |
| 671 | const mid = (log_min + log_max) / 2; |
| 672 | if (len > 1 << mid) { |
| 673 | shortMemset(mid, log_max, d, b, len); |
| 674 | } else { |
| 675 | shortMemset(log_min, mid, d, b, len); |
| 676 | } |
| 677 | } else { |
| 678 | const size = 1 << log_min; |
| 679 | |
| 680 | memsetSmallPowerOf2(d, b, size); |
| 681 | memsetSmallPowerOf2(d + len - size, b, size); |
| 682 | } |
| 683 | } |
| 684 | |
| 685 | fn fastMemset(dest: ?[*]u8, c: c_int, len: usize) callconv(.c) ?[*]u8 { |
| 686 | const b: u8 = @truncate(@as(c_uint, @bitCast(c))); |
| 687 | const n = std.simd.suggestVectorLength(u8) orelse @sizeOf(usize); |
| 688 | |
| 689 | const d = dest.?; |
| 690 | |
| 691 | if (len > 2 * n) { |
| 692 | memsetSmallPowerOf2(d, b, n); |
| 693 | |
| 694 | const begin_aligned = std.mem.alignBackward(usize, @intFromPtr(d) + n, n); |
| 695 | const end_aligned = std.mem.alignForward(usize, @intFromPtr(d) + len - n, n); |
| 696 | |
| 697 | const aligned_ptr: [*]align(n) u8 = @ptrFromInt(begin_aligned); |
| 698 | |
| 699 | var i: usize = 0; |
| 700 | while (true) { |
| 701 | memsetSmallPowerOf2(aligned_ptr + n * i, b, n); |
| 702 | |
| 703 | i += 1; |
| 704 | if (i == @divExact(end_aligned - begin_aligned, n)) |
| 705 | break; |
| 706 | } |
| 707 | |
| 708 | memsetSmallPowerOf2(d + len - n, b, n); |
| 709 | } else { |
| 710 | if (len == 0) return dest; |
| 711 | |
| 712 | shortMemset(0, @ctz(@as(usize, 2 * n)), d, b, len); |
| 713 | } |
| 714 | |
| 715 | return dest; |
| 716 | } |
| 717 | |
| 718 | fn smallMemset(dest: ?[*]u8, c: c_int, len: usize) callconv(.c) ?[*]u8 { |
| 654 | 719 | const b: u8 = @truncate(@as(c_uint, @bitCast(c))); |
| 655 | 720 | |
| 656 | 721 | if (len != 0) { |
| ... | ... | @@ -667,6 +732,11 @@ pub fn memset(dest: ?[*]u8, c: c_int, len: usize) callconv(.c) ?[*]u8 { |
| 667 | 732 | return dest; |
| 668 | 733 | } |
| 669 | 734 | |
| 735 | pub const memset = if (builtin.optimize == .small) |
| 736 | smallMemset |
| 737 | else |
| 738 | fastMemset; |
| 739 | |
| 670 | 740 | pub fn bcmp(vl: [*]allowzero const u8, vr: [*]allowzero const u8, n: usize) callconv(.c) c_int { |
| 671 | 741 | @setRuntimeSafety(false); |
| 672 | 742 | |