authorgravatar for matu3ba@users.noreply.github.commatu3ba <matu3ba@users.noreply.github.com> 2023-02-24 19:27:02+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-02-24 13:27:02-05:00
log97b9facb98cffa05064315d69a11b96836aa5be3
tree063bb8d02a752df2d33fc8d2d8a2b1def1ee3728
parent5f70c36fa88a17c045839b8b422e04db3b545426
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

compiler_rt: declutter int.zig, add mulXi3 tests (#14623)

- Combine mulXi3 routines for follow-up cleanup. - DRY up Dwords and Twords - rename both to HalveInt and use instance * Justification: Not all processors have word size 32 bit. * remove test file from CMakeLists * DRY things.

11 files changed, 294 insertions(+), 354 deletions(-)

CMakeLists.txt+3-5
...@@ -434,13 +434,12 @@ set(ZIG_STAGE2_SOURCES...@@ -434,13 +434,12 @@ set(ZIG_STAGE2_SOURCES
434 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/log10.zig"434 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/log10.zig"
435 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/log2.zig"435 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/log2.zig"
436 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/modti3.zig"436 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/modti3.zig"
437 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/mulXi3.zig"
437 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/muldf3.zig"438 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/muldf3.zig"
438 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/muldi3.zig"
439 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/mulf3.zig"439 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/mulf3.zig"
440 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/mulo.zig"440 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/mulo.zig"
441 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/mulsf3.zig"441 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/mulsf3.zig"
442 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/multf3.zig"442 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/multf3.zig"
443 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/multi3.zig"
444 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/mulxf3.zig"443 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/mulxf3.zig"
445 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/negXi2.zig"444 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/negXi2.zig"
446 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/negv.zig"445 "${CMAKE_SOURCE_DIR}/lib/compiler_rt/negv.zig"
...@@ -613,7 +612,6 @@ set(ZIG_STAGE2_SOURCES...@@ -613,7 +612,6 @@ set(ZIG_STAGE2_SOURCES
613 "${CMAKE_SOURCE_DIR}/src/link/tapi.zig"612 "${CMAKE_SOURCE_DIR}/src/link/tapi.zig"
614 "${CMAKE_SOURCE_DIR}/src/link/tapi/Tokenizer.zig"613 "${CMAKE_SOURCE_DIR}/src/link/tapi/Tokenizer.zig"
615 "${CMAKE_SOURCE_DIR}/src/link/tapi/parse.zig"614 "${CMAKE_SOURCE_DIR}/src/link/tapi/parse.zig"
616 "${CMAKE_SOURCE_DIR}/src/link/tapi/parse/test.zig"
617 "${CMAKE_SOURCE_DIR}/src/link/tapi/yaml.zig"615 "${CMAKE_SOURCE_DIR}/src/link/tapi/yaml.zig"
618 "${CMAKE_SOURCE_DIR}/src/main.zig"616 "${CMAKE_SOURCE_DIR}/src/main.zig"
619 "${CMAKE_SOURCE_DIR}/src/mingw.zig"617 "${CMAKE_SOURCE_DIR}/src/mingw.zig"
...@@ -753,7 +751,7 @@ set(BUILD_ZIG2_ARGS...@@ -753,7 +751,7 @@ set(BUILD_ZIG2_ARGS
753 --deps build_options751 --deps build_options
754 -target "${HOST_TARGET_TRIPLE}"752 -target "${HOST_TARGET_TRIPLE}"
755)753)
756 754
757add_custom_command(755add_custom_command(
758 OUTPUT "${ZIG2_C_SOURCE}"756 OUTPUT "${ZIG2_C_SOURCE}"
759 COMMAND zig1 ${BUILD_ZIG2_ARGS}757 COMMAND zig1 ${BUILD_ZIG2_ARGS}
...@@ -771,7 +769,7 @@ set(BUILD_COMPILER_RT_ARGS...@@ -771,7 +769,7 @@ set(BUILD_COMPILER_RT_ARGS
771 --deps build_options769 --deps build_options
772 -target "${HOST_TARGET_TRIPLE}"770 -target "${HOST_TARGET_TRIPLE}"
773)771)
774 772
775add_custom_command(773add_custom_command(
776 OUTPUT "${ZIG_COMPILER_RT_C_SOURCE}"774 OUTPUT "${ZIG_COMPILER_RT_C_SOURCE}"
777 COMMAND zig1 ${BUILD_COMPILER_RT_ARGS}775 COMMAND zig1 ${BUILD_COMPILER_RT_ARGS}
lib/compiler_rt.zig+1-2
...@@ -13,8 +13,7 @@ comptime {...@@ -13,8 +13,7 @@ comptime {
13 _ = @import("compiler_rt/shift.zig");13 _ = @import("compiler_rt/shift.zig");
14 _ = @import("compiler_rt/negXi2.zig");14 _ = @import("compiler_rt/negXi2.zig");
15 _ = @import("compiler_rt/int.zig");15 _ = @import("compiler_rt/int.zig");
16 _ = @import("compiler_rt/muldi3.zig");16 _ = @import("compiler_rt/mulXi3.zig");
17 _ = @import("compiler_rt/multi3.zig");
18 _ = @import("compiler_rt/divti3.zig");17 _ = @import("compiler_rt/divti3.zig");
19 _ = @import("compiler_rt/udivti3.zig");18 _ = @import("compiler_rt/udivti3.zig");
20 _ = @import("compiler_rt/modti3.zig");19 _ = @import("compiler_rt/modti3.zig");
lib/compiler_rt/common.zig+18
...@@ -1,5 +1,6 @@...@@ -1,5 +1,6 @@
1const std = @import("std");1const std = @import("std");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const native_endian = builtin.cpu.arch.endian();
34
4pub const linkage: std.builtin.GlobalLinkage = if (builtin.is_test) .Internal else .Weak;5pub const linkage: std.builtin.GlobalLinkage = if (builtin.is_test) .Internal else .Weak;
5/// Determines the symbol's visibility to other objects.6/// Determines the symbol's visibility to other objects.
...@@ -221,3 +222,20 @@ pub inline fn fneg(a: anytype) @TypeOf(a) {...@@ -221,3 +222,20 @@ pub inline fn fneg(a: anytype) @TypeOf(a) {
221 const negated = @bitCast(U, a) ^ sign_bit_mask;222 const negated = @bitCast(U, a) ^ sign_bit_mask;
222 return @bitCast(F, negated);223 return @bitCast(F, negated);
223}224}
225
226/// Allows to access underlying bits as two equally sized lower and higher
227/// signed or unsigned integers.
228pub fn HalveInt(comptime T: type, comptime signed_half: bool) type {
229 return extern union {
230 pub const bits = @divExact(@typeInfo(T).Int.bits, 2);
231 pub const HalfTU = std.meta.Int(.unsigned, bits);
232 pub const HalfTS = std.meta.Int(.signed, bits);
233 pub const HalfT = if (signed_half) HalfTS else HalfTU;
234
235 all: T,
236 s: if (native_endian == .Little)
237 extern struct { low: HalfT, high: HalfT }
238 else
239 extern struct { high: HalfT, low: HalfT },
240 };
241}
lib/compiler_rt/int.zig-57
...@@ -16,7 +16,6 @@ pub const panic = common.panic;...@@ -16,7 +16,6 @@ pub const panic = common.panic;
16comptime {16comptime {
17 @export(__divmodti4, .{ .name = "__divmodti4", .linkage = common.linkage, .visibility = common.visibility });17 @export(__divmodti4, .{ .name = "__divmodti4", .linkage = common.linkage, .visibility = common.visibility });
18 @export(__udivmoddi4, .{ .name = "__udivmoddi4", .linkage = common.linkage, .visibility = common.visibility });18 @export(__udivmoddi4, .{ .name = "__udivmoddi4", .linkage = common.linkage, .visibility = common.visibility });
19 @export(__mulsi3, .{ .name = "__mulsi3", .linkage = common.linkage, .visibility = common.visibility });
20 @export(__divmoddi4, .{ .name = "__divmoddi4", .linkage = common.linkage, .visibility = common.visibility });19 @export(__divmoddi4, .{ .name = "__divmoddi4", .linkage = common.linkage, .visibility = common.visibility });
21 if (common.want_aeabi) {20 if (common.want_aeabi) {
22 @export(__aeabi_idiv, .{ .name = "__aeabi_idiv", .linkage = common.linkage, .visibility = common.visibility });21 @export(__aeabi_idiv, .{ .name = "__aeabi_idiv", .linkage = common.linkage, .visibility = common.visibility });
...@@ -663,59 +662,3 @@ fn test_one_umodsi3(a: u32, b: u32, expected_r: u32) !void {...@@ -663,59 +662,3 @@ fn test_one_umodsi3(a: u32, b: u32, expected_r: u32) !void {
663 const r: u32 = __umodsi3(a, b);662 const r: u32 = __umodsi3(a, b);
664 try testing.expect(r == expected_r);663 try testing.expect(r == expected_r);
665}664}
666
667pub fn __mulsi3(a: i32, b: i32) callconv(.C) i32 {
668 var ua = @bitCast(u32, a);
669 var ub = @bitCast(u32, b);
670 var r: u32 = 0;
671
672 while (ua > 0) {
673 if ((ua & 1) != 0) r +%= ub;
674 ua >>= 1;
675 ub <<= 1;
676 }
677
678 return @bitCast(i32, r);
679}
680
681fn test_one_mulsi3(a: i32, b: i32, result: i32) !void {
682 try testing.expectEqual(result, __mulsi3(a, b));
683}
684
685test "mulsi3" {
686 try test_one_mulsi3(0, 0, 0);
687 try test_one_mulsi3(0, 1, 0);
688 try test_one_mulsi3(1, 0, 0);
689 try test_one_mulsi3(0, 10, 0);
690 try test_one_mulsi3(10, 0, 0);
691 try test_one_mulsi3(0, maxInt(i32), 0);
692 try test_one_mulsi3(maxInt(i32), 0, 0);
693 try test_one_mulsi3(0, -1, 0);
694 try test_one_mulsi3(-1, 0, 0);
695 try test_one_mulsi3(0, -10, 0);
696 try test_one_mulsi3(-10, 0, 0);
697 try test_one_mulsi3(0, minInt(i32), 0);
698 try test_one_mulsi3(minInt(i32), 0, 0);
699 try test_one_mulsi3(1, 1, 1);
700 try test_one_mulsi3(1, 10, 10);
701 try test_one_mulsi3(10, 1, 10);
702 try test_one_mulsi3(1, maxInt(i32), maxInt(i32));
703 try test_one_mulsi3(maxInt(i32), 1, maxInt(i32));
704 try test_one_mulsi3(1, -1, -1);
705 try test_one_mulsi3(1, -10, -10);
706 try test_one_mulsi3(-10, 1, -10);
707 try test_one_mulsi3(1, minInt(i32), minInt(i32));
708 try test_one_mulsi3(minInt(i32), 1, minInt(i32));
709 try test_one_mulsi3(46340, 46340, 2147395600);
710 try test_one_mulsi3(-46340, 46340, -2147395600);
711 try test_one_mulsi3(46340, -46340, -2147395600);
712 try test_one_mulsi3(-46340, -46340, 2147395600);
713 try test_one_mulsi3(4194303, 8192, @truncate(i32, 34359730176));
714 try test_one_mulsi3(-4194303, 8192, @truncate(i32, -34359730176));
715 try test_one_mulsi3(4194303, -8192, @truncate(i32, -34359730176));
716 try test_one_mulsi3(-4194303, -8192, @truncate(i32, 34359730176));
717 try test_one_mulsi3(8192, 4194303, @truncate(i32, 34359730176));
718 try test_one_mulsi3(-8192, 4194303, @truncate(i32, -34359730176));
719 try test_one_mulsi3(8192, -4194303, @truncate(i32, -34359730176));
720 try test_one_mulsi3(-8192, -4194303, @truncate(i32, 34359730176));
721}
lib/compiler_rt/mulXi3.zig created+101
...@@ -0,0 +1,101 @@
1const builtin = @import("builtin");
2const std = @import("std");
3const testing = std.testing;
4const common = @import("common.zig");
5const native_endian = builtin.cpu.arch.endian();
6
7pub const panic = common.panic;
8
9comptime {
10 @export(__mulsi3, .{ .name = "__mulsi3", .linkage = common.linkage, .visibility = common.visibility });
11 if (common.want_aeabi) {
12 @export(__aeabi_lmul, .{ .name = "__aeabi_lmul", .linkage = common.linkage, .visibility = common.visibility });
13 } else {
14 @export(__muldi3, .{ .name = "__muldi3", .linkage = common.linkage, .visibility = common.visibility });
15 }
16 if (common.want_windows_v2u64_abi) {
17 @export(__multi3_windows_x86_64, .{ .name = "__multi3", .linkage = common.linkage, .visibility = common.visibility });
18 } else {
19 @export(__multi3, .{ .name = "__multi3", .linkage = common.linkage, .visibility = common.visibility });
20 }
21}
22
23pub fn __mulsi3(a: i32, b: i32) callconv(.C) i32 {
24 var ua = @bitCast(u32, a);
25 var ub = @bitCast(u32, b);
26 var r: u32 = 0;
27
28 while (ua > 0) {
29 if ((ua & 1) != 0) r +%= ub;
30 ua >>= 1;
31 ub <<= 1;
32 }
33
34 return @bitCast(i32, r);
35}
36
37pub fn __muldi3(a: i64, b: i64) callconv(.C) i64 {
38 return mulX(i64, a, b);
39}
40
41fn __aeabi_lmul(a: i64, b: i64) callconv(.AAPCS) i64 {
42 return mulX(i64, a, b);
43}
44
45inline fn mulX(comptime T: type, a: T, b: T) T {
46 const word_t = common.HalveInt(T, false);
47 const x = word_t{ .all = a };
48 const y = word_t{ .all = b };
49 var r = switch (T) {
50 i64, i128 => word_t{ .all = muldXi(word_t.HalfT, x.s.low, y.s.low) },
51 else => unreachable,
52 };
53 r.s.high +%= x.s.high *% y.s.low +% x.s.low *% y.s.high;
54 return r.all;
55}
56
57fn DoubleInt(comptime T: type) type {
58 return switch (T) {
59 u32 => i64,
60 u64 => i128,
61 i32 => i64,
62 i64 => i128,
63 else => unreachable,
64 };
65}
66
67fn muldXi(comptime T: type, a: T, b: T) DoubleInt(T) {
68 const DT = DoubleInt(T);
69 const word_t = common.HalveInt(DT, false);
70 const bits_in_word_2 = @sizeOf(T) * 8 / 2;
71 const lower_mask = (~@as(T, 0)) >> bits_in_word_2;
72
73 var r: word_t = undefined;
74 r.s.low = (a & lower_mask) *% (b & lower_mask);
75 var t: T = r.s.low >> bits_in_word_2;
76 r.s.low &= lower_mask;
77 t += (a >> bits_in_word_2) *% (b & lower_mask);
78 r.s.low +%= (t & lower_mask) << bits_in_word_2;
79 r.s.high = t >> bits_in_word_2;
80 t = r.s.low >> bits_in_word_2;
81 r.s.low &= lower_mask;
82 t +%= (b >> bits_in_word_2) *% (a & lower_mask);
83 r.s.low +%= (t & lower_mask) << bits_in_word_2;
84 r.s.high +%= t >> bits_in_word_2;
85 r.s.high +%= (a >> bits_in_word_2) *% (b >> bits_in_word_2);
86 return r.all;
87}
88
89pub fn __multi3(a: i128, b: i128) callconv(.C) i128 {
90 return mulX(i128, a, b);
91}
92
93const v2u64 = @Vector(2, u64);
94
95fn __multi3_windows_x86_64(a: v2u64, b: v2u64) callconv(.C) v2u64 {
96 return @bitCast(v2u64, mulX(i128, @bitCast(i128, a), @bitCast(i128, b)));
97}
98
99test {
100 _ = @import("mulXi3_test.zig");
101}
lib/compiler_rt/mulXi3_test.zig created+147
...@@ -0,0 +1,147 @@
1const std = @import("std");
2const testing = std.testing;
3const mulXi3 = @import("mulXi3.zig");
4const maxInt = std.math.maxInt;
5const minInt = std.math.minInt;
6
7fn test_one_mulsi3(a: i32, b: i32, result: i32) !void {
8 try testing.expectEqual(result, mulXi3.__mulsi3(a, b));
9}
10
11fn test__muldi3(a: i64, b: i64, expected: i64) !void {
12 const x = mulXi3.__muldi3(a, b);
13 try testing.expect(x == expected);
14}
15
16fn test__multi3(a: i128, b: i128, expected: i128) !void {
17 const x = mulXi3.__multi3(a, b);
18 try testing.expect(x == expected);
19}
20
21test "mulsi3" {
22 try test_one_mulsi3(0, 0, 0);
23 try test_one_mulsi3(0, 1, 0);
24 try test_one_mulsi3(1, 0, 0);
25 try test_one_mulsi3(0, 10, 0);
26 try test_one_mulsi3(10, 0, 0);
27 try test_one_mulsi3(0, maxInt(i32), 0);
28 try test_one_mulsi3(maxInt(i32), 0, 0);
29 try test_one_mulsi3(0, -1, 0);
30 try test_one_mulsi3(-1, 0, 0);
31 try test_one_mulsi3(0, -10, 0);
32 try test_one_mulsi3(-10, 0, 0);
33 try test_one_mulsi3(0, minInt(i32), 0);
34 try test_one_mulsi3(minInt(i32), 0, 0);
35 try test_one_mulsi3(1, 1, 1);
36 try test_one_mulsi3(1, 10, 10);
37 try test_one_mulsi3(10, 1, 10);
38 try test_one_mulsi3(1, maxInt(i32), maxInt(i32));
39 try test_one_mulsi3(maxInt(i32), 1, maxInt(i32));
40 try test_one_mulsi3(1, -1, -1);
41 try test_one_mulsi3(1, -10, -10);
42 try test_one_mulsi3(-10, 1, -10);
43 try test_one_mulsi3(1, minInt(i32), minInt(i32));
44 try test_one_mulsi3(minInt(i32), 1, minInt(i32));
45 try test_one_mulsi3(46340, 46340, 2147395600);
46 try test_one_mulsi3(-46340, 46340, -2147395600);
47 try test_one_mulsi3(46340, -46340, -2147395600);
48 try test_one_mulsi3(-46340, -46340, 2147395600);
49 try test_one_mulsi3(4194303, 8192, @truncate(i32, 34359730176));
50 try test_one_mulsi3(-4194303, 8192, @truncate(i32, -34359730176));
51 try test_one_mulsi3(4194303, -8192, @truncate(i32, -34359730176));
52 try test_one_mulsi3(-4194303, -8192, @truncate(i32, 34359730176));
53 try test_one_mulsi3(8192, 4194303, @truncate(i32, 34359730176));
54 try test_one_mulsi3(-8192, 4194303, @truncate(i32, -34359730176));
55 try test_one_mulsi3(8192, -4194303, @truncate(i32, -34359730176));
56 try test_one_mulsi3(-8192, -4194303, @truncate(i32, 34359730176));
57}
58
59test "muldi3" {
60 try test__muldi3(0, 0, 0);
61 try test__muldi3(0, 1, 0);
62 try test__muldi3(1, 0, 0);
63 try test__muldi3(0, 10, 0);
64 try test__muldi3(10, 0, 0);
65 try test__muldi3(0, 81985529216486895, 0);
66 try test__muldi3(81985529216486895, 0, 0);
67
68 try test__muldi3(0, -1, 0);
69 try test__muldi3(-1, 0, 0);
70 try test__muldi3(0, -10, 0);
71 try test__muldi3(-10, 0, 0);
72 try test__muldi3(0, -81985529216486895, 0);
73 try test__muldi3(-81985529216486895, 0, 0);
74
75 try test__muldi3(1, 1, 1);
76 try test__muldi3(1, 10, 10);
77 try test__muldi3(10, 1, 10);
78 try test__muldi3(1, 81985529216486895, 81985529216486895);
79 try test__muldi3(81985529216486895, 1, 81985529216486895);
80
81 try test__muldi3(1, -1, -1);
82 try test__muldi3(1, -10, -10);
83 try test__muldi3(-10, 1, -10);
84 try test__muldi3(1, -81985529216486895, -81985529216486895);
85 try test__muldi3(-81985529216486895, 1, -81985529216486895);
86
87 try test__muldi3(3037000499, 3037000499, 9223372030926249001);
88 try test__muldi3(-3037000499, 3037000499, -9223372030926249001);
89 try test__muldi3(3037000499, -3037000499, -9223372030926249001);
90 try test__muldi3(-3037000499, -3037000499, 9223372030926249001);
91
92 try test__muldi3(4398046511103, 2097152, 9223372036852678656);
93 try test__muldi3(-4398046511103, 2097152, -9223372036852678656);
94 try test__muldi3(4398046511103, -2097152, -9223372036852678656);
95 try test__muldi3(-4398046511103, -2097152, 9223372036852678656);
96
97 try test__muldi3(2097152, 4398046511103, 9223372036852678656);
98 try test__muldi3(-2097152, 4398046511103, -9223372036852678656);
99 try test__muldi3(2097152, -4398046511103, -9223372036852678656);
100 try test__muldi3(-2097152, -4398046511103, 9223372036852678656);
101}
102
103test "multi3" {
104 try test__multi3(0, 0, 0);
105 try test__multi3(0, 1, 0);
106 try test__multi3(1, 0, 0);
107 try test__multi3(0, 10, 0);
108 try test__multi3(10, 0, 0);
109 try test__multi3(0, 81985529216486895, 0);
110 try test__multi3(81985529216486895, 0, 0);
111
112 try test__multi3(0, -1, 0);
113 try test__multi3(-1, 0, 0);
114 try test__multi3(0, -10, 0);
115 try test__multi3(-10, 0, 0);
116 try test__multi3(0, -81985529216486895, 0);
117 try test__multi3(-81985529216486895, 0, 0);
118
119 try test__multi3(1, 1, 1);
120 try test__multi3(1, 10, 10);
121 try test__multi3(10, 1, 10);
122 try test__multi3(1, 81985529216486895, 81985529216486895);
123 try test__multi3(81985529216486895, 1, 81985529216486895);
124
125 try test__multi3(1, -1, -1);
126 try test__multi3(1, -10, -10);
127 try test__multi3(-10, 1, -10);
128 try test__multi3(1, -81985529216486895, -81985529216486895);
129 try test__multi3(-81985529216486895, 1, -81985529216486895);
130
131 try test__multi3(3037000499, 3037000499, 9223372030926249001);
132 try test__multi3(-3037000499, 3037000499, -9223372030926249001);
133 try test__multi3(3037000499, -3037000499, -9223372030926249001);
134 try test__multi3(-3037000499, -3037000499, 9223372030926249001);
135
136 try test__multi3(4398046511103, 2097152, 9223372036852678656);
137 try test__multi3(-4398046511103, 2097152, -9223372036852678656);
138 try test__multi3(4398046511103, -2097152, -9223372036852678656);
139 try test__multi3(-4398046511103, -2097152, 9223372036852678656);
140
141 try test__multi3(2097152, 4398046511103, 9223372036852678656);
142 try test__multi3(-2097152, 4398046511103, -9223372036852678656);
143 try test__multi3(2097152, -4398046511103, -9223372036852678656);
144 try test__multi3(-2097152, -4398046511103, 9223372036852678656);
145
146 try test__multi3(0x00000000000000B504F333F9DE5BE000, 0x000000000000000000B504F333F9DE5B, 0x7FFFFFFFFFFFF328DF915DA296E8A000);
147}
lib/compiler_rt/muldi3.zig deleted-71
...@@ -1,71 +0,0 @@
1//! Ported from
2//! https://github.com/llvm/llvm-project/blob/llvmorg-9.0.0/compiler-rt/lib/builtins/muldi3.c
3
4const std = @import("std");
5const builtin = @import("builtin");
6const native_endian = builtin.cpu.arch.endian();
7const common = @import("common.zig");
8
9pub const panic = common.panic;
10
11comptime {
12 if (common.want_aeabi) {
13 @export(__aeabi_lmul, .{ .name = "__aeabi_lmul", .linkage = common.linkage, .visibility = common.visibility });
14 } else {
15 @export(__muldi3, .{ .name = "__muldi3", .linkage = common.linkage, .visibility = common.visibility });
16 }
17}
18
19pub fn __muldi3(a: i64, b: i64) callconv(.C) i64 {
20 return mul(a, b);
21}
22
23fn __aeabi_lmul(a: i64, b: i64) callconv(.AAPCS) i64 {
24 return mul(a, b);
25}
26
27inline fn mul(a: i64, b: i64) i64 {
28 const x = dwords{ .all = a };
29 const y = dwords{ .all = b };
30 var r = dwords{ .all = muldsi3(x.s.low, y.s.low) };
31 r.s.high +%= x.s.high *% y.s.low +% x.s.low *% y.s.high;
32 return r.all;
33}
34
35const dwords = extern union {
36 all: i64,
37 s: switch (native_endian) {
38 .Little => extern struct {
39 low: u32,
40 high: u32,
41 },
42 .Big => extern struct {
43 high: u32,
44 low: u32,
45 },
46 },
47};
48
49fn muldsi3(a: u32, b: u32) i64 {
50 const bits_in_word_2 = @sizeOf(i32) * 8 / 2;
51 const lower_mask = (~@as(u32, 0)) >> bits_in_word_2;
52
53 var r: dwords = undefined;
54 r.s.low = (a & lower_mask) *% (b & lower_mask);
55 var t: u32 = r.s.low >> bits_in_word_2;
56 r.s.low &= lower_mask;
57 t += (a >> bits_in_word_2) *% (b & lower_mask);
58 r.s.low +%= (t & lower_mask) << bits_in_word_2;
59 r.s.high = t >> bits_in_word_2;
60 t = r.s.low >> bits_in_word_2;
61 r.s.low &= lower_mask;
62 t +%= (b >> bits_in_word_2) *% (a & lower_mask);
63 r.s.low +%= (t & lower_mask) << bits_in_word_2;
64 r.s.high +%= t >> bits_in_word_2;
65 r.s.high +%= (a >> bits_in_word_2) *% (b >> bits_in_word_2);
66 return r.all;
67}
68
69test {
70 _ = @import("muldi3_test.zig");
71}
lib/compiler_rt/muldi3_test.zig deleted-51
...@@ -1,51 +0,0 @@
1const __muldi3 = @import("muldi3.zig").__muldi3;
2const testing = @import("std").testing;
3
4fn test__muldi3(a: i64, b: i64, expected: i64) !void {
5 const x = __muldi3(a, b);
6 try testing.expect(x == expected);
7}
8
9test "muldi3" {
10 try test__muldi3(0, 0, 0);
11 try test__muldi3(0, 1, 0);
12 try test__muldi3(1, 0, 0);
13 try test__muldi3(0, 10, 0);
14 try test__muldi3(10, 0, 0);
15 try test__muldi3(0, 81985529216486895, 0);
16 try test__muldi3(81985529216486895, 0, 0);
17
18 try test__muldi3(0, -1, 0);
19 try test__muldi3(-1, 0, 0);
20 try test__muldi3(0, -10, 0);
21 try test__muldi3(-10, 0, 0);
22 try test__muldi3(0, -81985529216486895, 0);
23 try test__muldi3(-81985529216486895, 0, 0);
24
25 try test__muldi3(1, 1, 1);
26 try test__muldi3(1, 10, 10);
27 try test__muldi3(10, 1, 10);
28 try test__muldi3(1, 81985529216486895, 81985529216486895);
29 try test__muldi3(81985529216486895, 1, 81985529216486895);
30
31 try test__muldi3(1, -1, -1);
32 try test__muldi3(1, -10, -10);
33 try test__muldi3(-10, 1, -10);
34 try test__muldi3(1, -81985529216486895, -81985529216486895);
35 try test__muldi3(-81985529216486895, 1, -81985529216486895);
36
37 try test__muldi3(3037000499, 3037000499, 9223372030926249001);
38 try test__muldi3(-3037000499, 3037000499, -9223372030926249001);
39 try test__muldi3(3037000499, -3037000499, -9223372030926249001);
40 try test__muldi3(-3037000499, -3037000499, 9223372030926249001);
41
42 try test__muldi3(4398046511103, 2097152, 9223372036852678656);
43 try test__muldi3(-4398046511103, 2097152, -9223372036852678656);
44 try test__muldi3(4398046511103, -2097152, -9223372036852678656);
45 try test__muldi3(-4398046511103, -2097152, 9223372036852678656);
46
47 try test__muldi3(2097152, 4398046511103, 9223372036852678656);
48 try test__muldi3(-2097152, 4398046511103, -9223372036852678656);
49 try test__muldi3(2097152, -4398046511103, -9223372036852678656);
50 try test__muldi3(-2097152, -4398046511103, 9223372036852678656);
51}
lib/compiler_rt/multi3.zig deleted-75
...@@ -1,75 +0,0 @@
1//! Ported from git@github.com:llvm-project/llvm-project-20170507.git
2//! ae684fad6d34858c014c94da69c15e7774a633c3
3//! 2018-08-13
4
5const std = @import("std");
6const builtin = @import("builtin");
7const native_endian = builtin.cpu.arch.endian();
8const common = @import("common.zig");
9
10pub const panic = common.panic;
11
12comptime {
13 if (common.want_windows_v2u64_abi) {
14 @export(__multi3_windows_x86_64, .{ .name = "__multi3", .linkage = common.linkage, .visibility = common.visibility });
15 } else {
16 @export(__multi3, .{ .name = "__multi3", .linkage = common.linkage, .visibility = common.visibility });
17 }
18}
19
20pub fn __multi3(a: i128, b: i128) callconv(.C) i128 {
21 return mul(a, b);
22}
23
24const v2u64 = @Vector(2, u64);
25
26fn __multi3_windows_x86_64(a: v2u64, b: v2u64) callconv(.C) v2u64 {
27 return @bitCast(v2u64, mul(@bitCast(i128, a), @bitCast(i128, b)));
28}
29
30inline fn mul(a: i128, b: i128) i128 {
31 const x = twords{ .all = a };
32 const y = twords{ .all = b };
33 var r = twords{ .all = mulddi3(x.s.low, y.s.low) };
34 r.s.high +%= x.s.high *% y.s.low +% x.s.low *% y.s.high;
35 return r.all;
36}
37
38fn mulddi3(a: u64, b: u64) i128 {
39 const bits_in_dword_2 = (@sizeOf(i64) * 8) / 2;
40 const lower_mask = ~@as(u64, 0) >> bits_in_dword_2;
41 var r: twords = undefined;
42 r.s.low = (a & lower_mask) *% (b & lower_mask);
43 var t: u64 = r.s.low >> bits_in_dword_2;
44 r.s.low &= lower_mask;
45 t +%= (a >> bits_in_dword_2) *% (b & lower_mask);
46 r.s.low +%= (t & lower_mask) << bits_in_dword_2;
47 r.s.high = t >> bits_in_dword_2;
48 t = r.s.low >> bits_in_dword_2;
49 r.s.low &= lower_mask;
50 t +%= (b >> bits_in_dword_2) *% (a & lower_mask);
51 r.s.low +%= (t & lower_mask) << bits_in_dword_2;
52 r.s.high +%= t >> bits_in_dword_2;
53 r.s.high +%= (a >> bits_in_dword_2) *% (b >> bits_in_dword_2);
54 return r.all;
55}
56
57const twords = extern union {
58 all: i128,
59 s: S,
60
61 const S = if (native_endian == .Little)
62 extern struct {
63 low: u64,
64 high: u64,
65 }
66 else
67 extern struct {
68 high: u64,
69 low: u64,
70 };
71};
72
73test {
74 _ = @import("multi3_test.zig");
75}
lib/compiler_rt/multi3_test.zig deleted-53
...@@ -1,53 +0,0 @@
1const __multi3 = @import("multi3.zig").__multi3;
2const testing = @import("std").testing;
3
4fn test__multi3(a: i128, b: i128, expected: i128) !void {
5 const x = __multi3(a, b);
6 try testing.expect(x == expected);
7}
8
9test "multi3" {
10 try test__multi3(0, 0, 0);
11 try test__multi3(0, 1, 0);
12 try test__multi3(1, 0, 0);
13 try test__multi3(0, 10, 0);
14 try test__multi3(10, 0, 0);
15 try test__multi3(0, 81985529216486895, 0);
16 try test__multi3(81985529216486895, 0, 0);
17
18 try test__multi3(0, -1, 0);
19 try test__multi3(-1, 0, 0);
20 try test__multi3(0, -10, 0);
21 try test__multi3(-10, 0, 0);
22 try test__multi3(0, -81985529216486895, 0);
23 try test__multi3(-81985529216486895, 0, 0);
24
25 try test__multi3(1, 1, 1);
26 try test__multi3(1, 10, 10);
27 try test__multi3(10, 1, 10);
28 try test__multi3(1, 81985529216486895, 81985529216486895);
29 try test__multi3(81985529216486895, 1, 81985529216486895);
30
31 try test__multi3(1, -1, -1);
32 try test__multi3(1, -10, -10);
33 try test__multi3(-10, 1, -10);
34 try test__multi3(1, -81985529216486895, -81985529216486895);
35 try test__multi3(-81985529216486895, 1, -81985529216486895);
36
37 try test__multi3(3037000499, 3037000499, 9223372030926249001);
38 try test__multi3(-3037000499, 3037000499, -9223372030926249001);
39 try test__multi3(3037000499, -3037000499, -9223372030926249001);
40 try test__multi3(-3037000499, -3037000499, 9223372030926249001);
41
42 try test__multi3(4398046511103, 2097152, 9223372036852678656);
43 try test__multi3(-4398046511103, 2097152, -9223372036852678656);
44 try test__multi3(4398046511103, -2097152, -9223372036852678656);
45 try test__multi3(-4398046511103, -2097152, 9223372036852678656);
46
47 try test__multi3(2097152, 4398046511103, 9223372036852678656);
48 try test__multi3(-2097152, 4398046511103, -9223372036852678656);
49 try test__multi3(2097152, -4398046511103, -9223372036852678656);
50 try test__multi3(-2097152, -4398046511103, 9223372036852678656);
51
52 try test__multi3(0x00000000000000B504F333F9DE5BE000, 0x000000000000000000B504F333F9DE5B, 0x7FFFFFFFFFFFF328DF915DA296E8A000);
53}
lib/compiler_rt/shift.zig+24-40
...@@ -1,7 +1,6 @@...@@ -1,7 +1,6 @@
1const std = @import("std");1const std = @import("std");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const Log2Int = std.math.Log2Int;3const Log2Int = std.math.Log2Int;
4const native_endian = builtin.cpu.arch.endian();
5const common = @import("common.zig");4const common = @import("common.zig");
65
7pub const panic = common.panic;6pub const panic = common.panic;
...@@ -27,39 +26,24 @@ comptime {...@@ -27,39 +26,24 @@ comptime {
27 }26 }
28}27}
2928
30fn Dwords(comptime T: type, comptime signed_half: bool) type {
31 return extern union {
32 const bits = @divExact(@typeInfo(T).Int.bits, 2);
33 const HalfTU = std.meta.Int(.unsigned, bits);
34 const HalfTS = std.meta.Int(.signed, bits);
35 const HalfT = if (signed_half) HalfTS else HalfTU;
36
37 all: T,
38 s: if (native_endian == .Little)
39 extern struct { low: HalfT, high: HalfT }
40 else
41 extern struct { high: HalfT, low: HalfT },
42 };
43}
44
45// Arithmetic shift left: shift in 0 from right to left29// Arithmetic shift left: shift in 0 from right to left
46// Precondition: 0 <= b < bits_in_dword30// Precondition: 0 <= b < bits_in_dword
47inline fn ashlXi3(comptime T: type, a: T, b: i32) T {31inline fn ashlXi3(comptime T: type, a: T, b: i32) T {
48 const dwords = Dwords(T, false);32 const word_t = common.HalveInt(T, false);
49 const S = Log2Int(dwords.HalfT);33 const S = Log2Int(word_t.HalfT);
5034
51 const input = dwords{ .all = a };35 const input = word_t{ .all = a };
52 var output: dwords = undefined;36 var output: word_t = undefined;
5337
54 if (b >= dwords.bits) {38 if (b >= word_t.bits) {
55 output.s.low = 0;39 output.s.low = 0;
56 output.s.high = input.s.low << @intCast(S, b - dwords.bits);40 output.s.high = input.s.low << @intCast(S, b - word_t.bits);
57 } else if (b == 0) {41 } else if (b == 0) {
58 return a;42 return a;
59 } else {43 } else {
60 output.s.low = input.s.low << @intCast(S, b);44 output.s.low = input.s.low << @intCast(S, b);
61 output.s.high = input.s.high << @intCast(S, b);45 output.s.high = input.s.high << @intCast(S, b);
62 output.s.high |= input.s.low >> @intCast(S, dwords.bits - b);46 output.s.high |= input.s.low >> @intCast(S, word_t.bits - b);
63 }47 }
6448
65 return output.all;49 return output.all;
...@@ -68,24 +52,24 @@ inline fn ashlXi3(comptime T: type, a: T, b: i32) T {...@@ -68,24 +52,24 @@ inline fn ashlXi3(comptime T: type, a: T, b: i32) T {
68// Arithmetic shift right: shift in 1 from left to right52// Arithmetic shift right: shift in 1 from left to right
69// Precondition: 0 <= b < T.bit_count53// Precondition: 0 <= b < T.bit_count
70inline fn ashrXi3(comptime T: type, a: T, b: i32) T {54inline fn ashrXi3(comptime T: type, a: T, b: i32) T {
71 const dwords = Dwords(T, true);55 const word_t = common.HalveInt(T, true);
72 const S = Log2Int(dwords.HalfT);56 const S = Log2Int(word_t.HalfT);
7357
74 const input = dwords{ .all = a };58 const input = word_t{ .all = a };
75 var output: dwords = undefined;59 var output: word_t = undefined;
7660
77 if (b >= dwords.bits) {61 if (b >= word_t.bits) {
78 output.s.high = input.s.high >> (dwords.bits - 1);62 output.s.high = input.s.high >> (word_t.bits - 1);
79 output.s.low = input.s.high >> @intCast(S, b - dwords.bits);63 output.s.low = input.s.high >> @intCast(S, b - word_t.bits);
80 } else if (b == 0) {64 } else if (b == 0) {
81 return a;65 return a;
82 } else {66 } else {
83 output.s.high = input.s.high >> @intCast(S, b);67 output.s.high = input.s.high >> @intCast(S, b);
84 output.s.low = input.s.high << @intCast(S, dwords.bits - b);68 output.s.low = input.s.high << @intCast(S, word_t.bits - b);
85 // Avoid sign-extension here69 // Avoid sign-extension here
86 output.s.low |= @bitCast(70 output.s.low |= @bitCast(
87 dwords.HalfT,71 word_t.HalfT,
88 @bitCast(dwords.HalfTU, input.s.low) >> @intCast(S, b),72 @bitCast(word_t.HalfTU, input.s.low) >> @intCast(S, b),
89 );73 );
90 }74 }
9175
...@@ -95,20 +79,20 @@ inline fn ashrXi3(comptime T: type, a: T, b: i32) T {...@@ -95,20 +79,20 @@ inline fn ashrXi3(comptime T: type, a: T, b: i32) T {
95// Logical shift right: shift in 0 from left to right79// Logical shift right: shift in 0 from left to right
96// Precondition: 0 <= b < T.bit_count80// Precondition: 0 <= b < T.bit_count
97inline fn lshrXi3(comptime T: type, a: T, b: i32) T {81inline fn lshrXi3(comptime T: type, a: T, b: i32) T {
98 const dwords = Dwords(T, false);82 const word_t = common.HalveInt(T, false);
99 const S = Log2Int(dwords.HalfT);83 const S = Log2Int(word_t.HalfT);
10084
101 const input = dwords{ .all = a };85 const input = word_t{ .all = a };
102 var output: dwords = undefined;86 var output: word_t = undefined;
10387
104 if (b >= dwords.bits) {88 if (b >= word_t.bits) {
105 output.s.high = 0;89 output.s.high = 0;
106 output.s.low = input.s.high >> @intCast(S, b - dwords.bits);90 output.s.low = input.s.high >> @intCast(S, b - word_t.bits);
107 } else if (b == 0) {91 } else if (b == 0) {
108 return a;92 return a;
109 } else {93 } else {
110 output.s.high = input.s.high >> @intCast(S, b);94 output.s.high = input.s.high >> @intCast(S, b);
111 output.s.low = input.s.high << @intCast(S, dwords.bits - b);95 output.s.low = input.s.high << @intCast(S, word_t.bits - b);
112 output.s.low |= input.s.low >> @intCast(S, b);96 output.s.low |= input.s.low >> @intCast(S, b);
113 }97 }
11498