authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-10-31 11:20:43+00:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2025-11-12 16:00:16+00:00
log20bd5e801826121ffa72ee54e3788bdb371b0fbc
treefeafaa7e61a82983cb97f037e8e6f3cc8104a37c
parentc091e27aac9d51cb3af06904c3039a8c316e5b89
signaturelock-open Commit is signed but in an unrecognized format.

compiler-rt: remove dead code

`__addosi4`, `__addodi4`, `__addoti4`, `__subosi4`, `__subodi4`, and `__suboti4` were all functions which we invented for no apparent reason. Neither LLVM, nor GCC, nor the Zig compiler use these functions. It appears the functions were created in a kind of misunderstanding of an old language proposal; see https://github.com/ziglang/zig/pull/10824. There is no benefit to these functions existing; if a Zig compiler backend needs this operation, it is trivial to implement, and *far* simpler than calling a compiler-rt routine. Therefore, this commit deletes them. A small amount of that code was used by other parts of compiler-rt; the logic is trivial so has just been inlined where needed. I also chose to quickly implement `__addvdi3` (a standard function) because it is trivial and we already implement the `sub` parallel.

14 files changed, 42 insertions(+), 591 deletions(-)

CMakeLists.txt+1-2
...@@ -211,10 +211,10 @@ set(ZIG_STAGE2_SOURCES...@@ -211,10 +211,10 @@ set(ZIG_STAGE2_SOURCES
211 lib/compiler_rt/absvti2.zig211 lib/compiler_rt/absvti2.zig
212 lib/compiler_rt/adddf3.zig212 lib/compiler_rt/adddf3.zig
213 lib/compiler_rt/addf3.zig213 lib/compiler_rt/addf3.zig
214 lib/compiler_rt/addo.zig
215 lib/compiler_rt/addsf3.zig214 lib/compiler_rt/addsf3.zig
216 lib/compiler_rt/addtf3.zig215 lib/compiler_rt/addtf3.zig
217 lib/compiler_rt/addvsi3.zig216 lib/compiler_rt/addvsi3.zig
217 lib/compiler_rt/addvdi3.zig
218 lib/compiler_rt/addxf3.zig218 lib/compiler_rt/addxf3.zig
219 lib/compiler_rt/arm.zig219 lib/compiler_rt/arm.zig
220 lib/compiler_rt/atomics.zig220 lib/compiler_rt/atomics.zig
...@@ -354,7 +354,6 @@ set(ZIG_STAGE2_SOURCES...@@ -354,7 +354,6 @@ set(ZIG_STAGE2_SOURCES
354 lib/compiler_rt/sqrt.zig354 lib/compiler_rt/sqrt.zig
355 lib/compiler_rt/stack_probe.zig355 lib/compiler_rt/stack_probe.zig
356 lib/compiler_rt/subdf3.zig356 lib/compiler_rt/subdf3.zig
357 lib/compiler_rt/subo.zig
358 lib/compiler_rt/subsf3.zig357 lib/compiler_rt/subsf3.zig
359 lib/compiler_rt/subtf3.zig358 lib/compiler_rt/subtf3.zig
360 lib/compiler_rt/subvdi3.zig359 lib/compiler_rt/subvdi3.zig
lib/compiler_rt.zig+3-2
...@@ -28,12 +28,13 @@ comptime {...@@ -28,12 +28,13 @@ comptime {
28 _ = @import("compiler_rt/negv.zig");28 _ = @import("compiler_rt/negv.zig");
2929
30 _ = @import("compiler_rt/addvsi3.zig");30 _ = @import("compiler_rt/addvsi3.zig");
31 _ = @import("compiler_rt/addvdi3.zig");
32
31 _ = @import("compiler_rt/subvsi3.zig");33 _ = @import("compiler_rt/subvsi3.zig");
32 _ = @import("compiler_rt/subvdi3.zig");34 _ = @import("compiler_rt/subvdi3.zig");
35
33 _ = @import("compiler_rt/mulvsi3.zig");36 _ = @import("compiler_rt/mulvsi3.zig");
3437
35 _ = @import("compiler_rt/addo.zig");
36 _ = @import("compiler_rt/subo.zig");
37 _ = @import("compiler_rt/mulo.zig");38 _ = @import("compiler_rt/mulo.zig");
3839
39 // Float routines40 // Float routines
lib/compiler_rt/addo.zig deleted-46
...@@ -1,46 +0,0 @@
1const std = @import("std");
2const common = @import("./common.zig");
3pub const panic = @import("common.zig").panic;
4
5comptime {
6 @export(&__addosi4, .{ .name = "__addosi4", .linkage = common.linkage, .visibility = common.visibility });
7 @export(&__addodi4, .{ .name = "__addodi4", .linkage = common.linkage, .visibility = common.visibility });
8 @export(&__addoti4, .{ .name = "__addoti4", .linkage = common.linkage, .visibility = common.visibility });
9}
10
11// addo - add overflow
12// * return a+%b.
13// * return if a+b overflows => 1 else => 0
14// - addoXi4_generic as default
15
16inline fn addoXi4_generic(comptime ST: type, a: ST, b: ST, overflow: *c_int) ST {
17 @setRuntimeSafety(common.test_safety);
18 overflow.* = 0;
19 const sum: ST = a +% b;
20 // Hackers Delight: section Overflow Detection, subsection Signed Add/Subtract
21 // Let sum = a +% b == a + b + carry == wraparound addition.
22 // Overflow in a+b+carry occurs, iff a and b have opposite signs
23 // and the sign of a+b+carry is the same as a (or equivalently b).
24 // Slower routine: res = ~(a ^ b) & ((sum ^ a)
25 // Faster routine: res = (sum ^ a) & (sum ^ b)
26 // Overflow occurred, iff (res < 0)
27 if (((sum ^ a) & (sum ^ b)) < 0)
28 overflow.* = 1;
29 return sum;
30}
31
32pub fn __addosi4(a: i32, b: i32, overflow: *c_int) callconv(.c) i32 {
33 return addoXi4_generic(i32, a, b, overflow);
34}
35pub fn __addodi4(a: i64, b: i64, overflow: *c_int) callconv(.c) i64 {
36 return addoXi4_generic(i64, a, b, overflow);
37}
38pub fn __addoti4(a: i128, b: i128, overflow: *c_int) callconv(.c) i128 {
39 return addoXi4_generic(i128, a, b, overflow);
40}
41
42test {
43 _ = @import("addosi4_test.zig");
44 _ = @import("addodi4_test.zig");
45 _ = @import("addoti4_test.zig");
46}
lib/compiler_rt/addodi4_test.zig deleted-77
...@@ -1,77 +0,0 @@
1const addv = @import("addo.zig");
2const std = @import("std");
3const testing = std.testing;
4const math = std.math;
5
6fn test__addodi4(a: i64, b: i64) !void {
7 var result_ov: c_int = undefined;
8 var expected_ov: c_int = undefined;
9 const result = addv.__addodi4(a, b, &result_ov);
10 const expected: i64 = simple_addodi4(a, b, &expected_ov);
11 try testing.expectEqual(expected, result);
12 try testing.expectEqual(expected_ov, result_ov);
13}
14
15fn simple_addodi4(a: i64, b: i64, overflow: *c_int) i64 {
16 overflow.* = 0;
17 const min: i64 = math.minInt(i64);
18 const max: i64 = math.maxInt(i64);
19 if (((a > 0) and (b > max - a)) or
20 ((a < 0) and (b < min - a)))
21 overflow.* = 1;
22 return a +% b;
23}
24
25test "addodi4" {
26 const min: i64 = math.minInt(i64);
27 const max: i64 = math.maxInt(i64);
28 var i: i64 = 1;
29 while (i < max) : (i *|= 2) {
30 try test__addodi4(i, i);
31 try test__addodi4(-i, -i);
32 try test__addodi4(i, -i);
33 try test__addodi4(-i, i);
34 }
35
36 // edge cases
37 // 0 + 0 = 0
38 // MIN + MIN overflow
39 // MAX + MAX overflow
40 // 0 + MIN MIN
41 // 0 + MAX MAX
42 // MIN + 0 MIN
43 // MAX + 0 MAX
44 // MIN + MAX -1
45 // MAX + MIN -1
46 try test__addodi4(0, 0);
47 try test__addodi4(min, min);
48 try test__addodi4(max, max);
49 try test__addodi4(0, min);
50 try test__addodi4(0, max);
51 try test__addodi4(min, 0);
52 try test__addodi4(max, 0);
53 try test__addodi4(min, max);
54 try test__addodi4(max, min);
55
56 // derived edge cases
57 // MIN+1 + MIN overflow
58 // MAX-1 + MAX overflow
59 // 1 + MIN = MIN+1
60 // -1 + MIN overflow
61 // -1 + MAX = MAX-1
62 // +1 + MAX overflow
63 // MIN + 1 = MIN+1
64 // MIN + -1 overflow
65 // MAX + 1 overflow
66 // MAX + -1 = MAX-1
67 try test__addodi4(min + 1, min);
68 try test__addodi4(max - 1, max);
69 try test__addodi4(1, min);
70 try test__addodi4(-1, min);
71 try test__addodi4(-1, max);
72 try test__addodi4(1, max);
73 try test__addodi4(min, 1);
74 try test__addodi4(min, -1);
75 try test__addodi4(max, -1);
76 try test__addodi4(max, 1);
77}
lib/compiler_rt/addosi4_test.zig deleted-78
...@@ -1,78 +0,0 @@
1const addv = @import("addo.zig");
2const testing = @import("std").testing;
3
4fn test__addosi4(a: i32, b: i32) !void {
5 var result_ov: c_int = undefined;
6 var expected_ov: c_int = undefined;
7 const result = addv.__addosi4(a, b, &result_ov);
8 const expected: i32 = simple_addosi4(a, b, &expected_ov);
9 try testing.expectEqual(expected, result);
10 try testing.expectEqual(expected_ov, result_ov);
11}
12
13fn simple_addosi4(a: i32, b: i32, overflow: *c_int) i32 {
14 overflow.* = 0;
15 const min: i32 = -2147483648;
16 const max: i32 = 2147483647;
17 if (((a > 0) and (b > max - a)) or
18 ((a < 0) and (b < min - a)))
19 overflow.* = 1;
20 return a +% b;
21}
22
23test "addosi4" {
24 // -2^31 <= i32 <= 2^31-1
25 // 2^31 = 2147483648
26 // 2^31-1 = 2147483647
27 const min: i32 = -2147483648;
28 const max: i32 = 2147483647;
29 var i: i32 = 1;
30 while (i < max) : (i *|= 2) {
31 try test__addosi4(i, i);
32 try test__addosi4(-i, -i);
33 try test__addosi4(i, -i);
34 try test__addosi4(-i, i);
35 }
36
37 // edge cases
38 // 0 + 0 = 0
39 // MIN + MIN overflow
40 // MAX + MAX overflow
41 // 0 + MIN MIN
42 // 0 + MAX MAX
43 // MIN + 0 MIN
44 // MAX + 0 MAX
45 // MIN + MAX -1
46 // MAX + MIN -1
47 try test__addosi4(0, 0);
48 try test__addosi4(min, min);
49 try test__addosi4(max, max);
50 try test__addosi4(0, min);
51 try test__addosi4(0, max);
52 try test__addosi4(min, 0);
53 try test__addosi4(max, 0);
54 try test__addosi4(min, max);
55 try test__addosi4(max, min);
56
57 // derived edge cases
58 // MIN+1 + MIN overflow
59 // MAX-1 + MAX overflow
60 // 1 + MIN = MIN+1
61 // -1 + MIN overflow
62 // -1 + MAX = MAX-1
63 // +1 + MAX overflow
64 // MIN + 1 = MIN+1
65 // MIN + -1 overflow
66 // MAX + 1 overflow
67 // MAX + -1 = MAX-1
68 try test__addosi4(min + 1, min);
69 try test__addosi4(max - 1, max);
70 try test__addosi4(1, min);
71 try test__addosi4(-1, min);
72 try test__addosi4(-1, max);
73 try test__addosi4(1, max);
74 try test__addosi4(min, 1);
75 try test__addosi4(min, -1);
76 try test__addosi4(max, -1);
77 try test__addosi4(max, 1);
78}
lib/compiler_rt/addoti4_test.zig deleted-80
...@@ -1,80 +0,0 @@
1const addv = @import("addo.zig");
2const builtin = @import("builtin");
3const std = @import("std");
4const testing = std.testing;
5const math = std.math;
6
7fn test__addoti4(a: i128, b: i128) !void {
8 var result_ov: c_int = undefined;
9 var expected_ov: c_int = undefined;
10 const result = addv.__addoti4(a, b, &result_ov);
11 const expected: i128 = simple_addoti4(a, b, &expected_ov);
12 try testing.expectEqual(expected, result);
13 try testing.expectEqual(expected_ov, result_ov);
14}
15
16fn simple_addoti4(a: i128, b: i128, overflow: *c_int) i128 {
17 overflow.* = 0;
18 const min: i128 = math.minInt(i128);
19 const max: i128 = math.maxInt(i128);
20 if (((a > 0) and (b > max - a)) or
21 ((a < 0) and (b < min - a)))
22 overflow.* = 1;
23 return a +% b;
24}
25
26test "addoti4" {
27 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
28
29 const min: i128 = math.minInt(i128);
30 const max: i128 = math.maxInt(i128);
31 var i: i128 = 1;
32 while (i < max) : (i *|= 2) {
33 try test__addoti4(i, i);
34 try test__addoti4(-i, -i);
35 try test__addoti4(i, -i);
36 try test__addoti4(-i, i);
37 }
38
39 // edge cases
40 // 0 + 0 = 0
41 // MIN + MIN overflow
42 // MAX + MAX overflow
43 // 0 + MIN MIN
44 // 0 + MAX MAX
45 // MIN + 0 MIN
46 // MAX + 0 MAX
47 // MIN + MAX -1
48 // MAX + MIN -1
49 try test__addoti4(0, 0);
50 try test__addoti4(min, min);
51 try test__addoti4(max, max);
52 try test__addoti4(0, min);
53 try test__addoti4(0, max);
54 try test__addoti4(min, 0);
55 try test__addoti4(max, 0);
56 try test__addoti4(min, max);
57 try test__addoti4(max, min);
58
59 // derived edge cases
60 // MIN+1 + MIN overflow
61 // MAX-1 + MAX overflow
62 // 1 + MIN = MIN+1
63 // -1 + MIN overflow
64 // -1 + MAX = MAX-1
65 // +1 + MAX overflow
66 // MIN + 1 = MIN+1
67 // MIN + -1 overflow
68 // MAX + 1 overflow
69 // MAX + -1 = MAX-1
70 try test__addoti4(min + 1, min);
71 try test__addoti4(max - 1, max);
72 try test__addoti4(1, min);
73 try test__addoti4(-1, min);
74 try test__addoti4(-1, max);
75 try test__addoti4(1, max);
76 try test__addoti4(min, 1);
77 try test__addoti4(min, -1);
78 try test__addoti4(max, -1);
79 try test__addoti4(max, 1);
80}
lib/compiler_rt/addvdi3.zig created+26
...@@ -0,0 +1,26 @@
1const common = @import("./common.zig");
2const testing = @import("std").testing;
3
4pub const panic = common.panic;
5
6comptime {
7 @export(&__addvdi3, .{ .name = "__addvdi3", .linkage = common.linkage, .visibility = common.visibility });
8}
9
10pub fn __addvdi3(a: i64, b: i64) callconv(.c) i64 {
11 const sum = a +% b;
12 // Overflow occurred iff both operands have the same sign, and the sign of the sum does
13 // not match it. In other words, iff the sum sign is not the sign of either operand.
14 if (((sum ^ a) & (sum ^ b)) < 0) @panic("compiler-rt: integer overflow");
15 return sum;
16}
17
18test "addvdi3" {
19 // const min: i64 = -9223372036854775808
20 // const max: i64 = 9223372036854775807
21 // TODO write panic handler for testing panics
22 // try test__addvdi3(-9223372036854775808, -1, -1); // panic
23 // try test__addvdi3(9223372036854775807, 1, 1); // panic
24 try testing.expectEqual(-9223372036854775808, __addvdi3(-9223372036854775807, -1));
25 try testing.expectEqual(9223372036854775807, __addvdi3(9223372036854775806, 1));
26}
lib/compiler_rt/addvsi3.zig+4-4
...@@ -1,4 +1,3 @@...@@ -1,4 +1,3 @@
1const addv = @import("addo.zig");
2const common = @import("./common.zig");1const common = @import("./common.zig");
3const testing = @import("std").testing;2const testing = @import("std").testing;
43
...@@ -9,9 +8,10 @@ comptime {...@@ -9,9 +8,10 @@ comptime {
9}8}
109
11pub fn __addvsi3(a: i32, b: i32) callconv(.c) i32 {10pub fn __addvsi3(a: i32, b: i32) callconv(.c) i32 {
12 var overflow: c_int = 0;11 const sum = a +% b;
13 const sum = addv.__addosi4(a, b, &overflow);12 // Overflow occurred iff both operands have the same sign, and the sign of the sum does
14 if (overflow != 0) @panic("compiler-rt: integer overflow");13 // not match it. In other words, iff the sum sign is not the sign of either operand.
14 if (((sum ^ a) & (sum ^ b)) < 0) @panic("compiler-rt: integer overflow");
15 return sum;15 return sum;
16}16}
1717
lib/compiler_rt/subo.zig deleted-47
...@@ -1,47 +0,0 @@
1//! subo - subtract overflow
2//! * return a-%b.
3//! * return if a-b overflows => 1 else => 0
4//! - suboXi4_generic as default
5
6const std = @import("std");
7const builtin = @import("builtin");
8const common = @import("common.zig");
9
10pub const panic = common.panic;
11
12comptime {
13 @export(&__subosi4, .{ .name = "__subosi4", .linkage = common.linkage, .visibility = common.visibility });
14 @export(&__subodi4, .{ .name = "__subodi4", .linkage = common.linkage, .visibility = common.visibility });
15 @export(&__suboti4, .{ .name = "__suboti4", .linkage = common.linkage, .visibility = common.visibility });
16}
17
18pub fn __subosi4(a: i32, b: i32, overflow: *c_int) callconv(.c) i32 {
19 return suboXi4_generic(i32, a, b, overflow);
20}
21pub fn __subodi4(a: i64, b: i64, overflow: *c_int) callconv(.c) i64 {
22 return suboXi4_generic(i64, a, b, overflow);
23}
24pub fn __suboti4(a: i128, b: i128, overflow: *c_int) callconv(.c) i128 {
25 return suboXi4_generic(i128, a, b, overflow);
26}
27
28inline fn suboXi4_generic(comptime ST: type, a: ST, b: ST, overflow: *c_int) ST {
29 overflow.* = 0;
30 const sum: ST = a -% b;
31 // Hackers Delight: section Overflow Detection, subsection Signed Add/Subtract
32 // Let sum = a -% b == a - b - carry == wraparound subtraction.
33 // Overflow in a-b-carry occurs, iff a and b have opposite signs
34 // and the sign of a-b-carry is opposite of a (or equivalently same as b).
35 // Faster routine: res = (a ^ b) & (sum ^ a)
36 // Slower routine: res = (sum^a) & ~(sum^b)
37 // Overflow occurred, iff (res < 0)
38 if (((a ^ b) & (sum ^ a)) < 0)
39 overflow.* = 1;
40 return sum;
41}
42
43test {
44 _ = @import("subosi4_test.zig");
45 _ = @import("subodi4_test.zig");
46 _ = @import("suboti4_test.zig");
47}
lib/compiler_rt/subodi4_test.zig deleted-81
...@@ -1,81 +0,0 @@
1const subo = @import("subo.zig");
2const std = @import("std");
3const testing = std.testing;
4const math = std.math;
5
6fn test__subodi4(a: i64, b: i64) !void {
7 var result_ov: c_int = undefined;
8 var expected_ov: c_int = undefined;
9 const result = subo.__subodi4(a, b, &result_ov);
10 const expected: i64 = simple_subodi4(a, b, &expected_ov);
11 try testing.expectEqual(expected, result);
12 try testing.expectEqual(expected_ov, result_ov);
13}
14
15// 2 cases on evaluating `a-b`:
16// 1. `a-b` may underflow, iff b>0 && a<0 and a-b < min <=> a<min+b
17// 2. `a-b` may overflow, iff b<0 && a>0 and a-b > max <=> a>max+b
18// `-b` evaluation may overflow, iff b==min, but this is handled by the hardware
19pub fn simple_subodi4(a: i64, b: i64, overflow: *c_int) i64 {
20 overflow.* = 0;
21 const min: i64 = math.minInt(i64);
22 const max: i64 = math.maxInt(i64);
23 if (((b > 0) and (a < min + b)) or
24 ((b < 0) and (a > max + b)))
25 overflow.* = 1;
26 return a -% b;
27}
28
29test "subodi3" {
30 const min: i64 = math.minInt(i64);
31 const max: i64 = math.maxInt(i64);
32 var i: i64 = 1;
33 while (i < max) : (i *|= 2) {
34 try test__subodi4(i, i);
35 try test__subodi4(-i, -i);
36 try test__subodi4(i, -i);
37 try test__subodi4(-i, i);
38 }
39
40 // edge cases
41 // 0 - 0 = 0
42 // MIN - MIN = 0
43 // MAX - MAX = 0
44 // 0 - MIN overflow
45 // 0 - MAX = MIN+1
46 // MIN - 0 = MIN
47 // MAX - 0 = MAX
48 // MIN - MAX overflow
49 // MAX - MIN overflow
50 try test__subodi4(0, 0);
51 try test__subodi4(min, min);
52 try test__subodi4(max, max);
53 try test__subodi4(0, min);
54 try test__subodi4(0, max);
55 try test__subodi4(min, 0);
56 try test__subodi4(max, 0);
57 try test__subodi4(min, max);
58 try test__subodi4(max, min);
59
60 // derived edge cases
61 // MIN+1 - MIN = 1
62 // MAX-1 - MAX = -1
63 // 1 - MIN overflow
64 // -1 - MIN = MAX
65 // -1 - MAX = MIN
66 // +1 - MAX = MIN+2
67 // MIN - 1 overflow
68 // MIN - -1 = MIN+1
69 // MAX - 1 = MAX-1
70 // MAX - -1 overflow
71 try test__subodi4(min + 1, min);
72 try test__subodi4(max - 1, max);
73 try test__subodi4(1, min);
74 try test__subodi4(-1, min);
75 try test__subodi4(-1, max);
76 try test__subodi4(1, max);
77 try test__subodi4(min, 1);
78 try test__subodi4(min, -1);
79 try test__subodi4(max, -1);
80 try test__subodi4(max, 1);
81}
lib/compiler_rt/subosi4_test.zig deleted-82
...@@ -1,82 +0,0 @@
1const subo = @import("subo.zig");
2const testing = @import("std").testing;
3
4fn test__subosi4(a: i32, b: i32) !void {
5 var result_ov: c_int = undefined;
6 var expected_ov: c_int = undefined;
7 const result = subo.__subosi4(a, b, &result_ov);
8 const expected: i32 = simple_subosi4(a, b, &expected_ov);
9 try testing.expectEqual(expected, result);
10 try testing.expectEqual(expected_ov, result_ov);
11}
12
13// 2 cases on evaluating `a-b`:
14// 1. `a-b` may underflow, iff b>0 && a<0 and a-b < min <=> a<min+b
15// 2. `a-b` may overflow, iff b<0 && a>0 and a-b > max <=> a>max+b
16// `-b` evaluation may overflow, iff b==min, but this is handled by the hardware
17pub fn simple_subosi4(a: i32, b: i32, overflow: *c_int) i32 {
18 overflow.* = 0;
19 const min: i32 = -2147483648;
20 const max: i32 = 2147483647;
21 if (((b > 0) and (a < min + b)) or
22 ((b < 0) and (a > max + b)))
23 overflow.* = 1;
24 return a -% b;
25}
26
27test "subosi3" {
28 // -2^31 <= i32 <= 2^31-1
29 // 2^31 = 2147483648
30 // 2^31-1 = 2147483647
31 const min: i32 = -2147483648;
32 const max: i32 = 2147483647;
33 var i: i32 = 1;
34 while (i < max) : (i *|= 2) {
35 try test__subosi4(i, i);
36 try test__subosi4(-i, -i);
37 try test__subosi4(i, -i);
38 try test__subosi4(-i, i);
39 }
40
41 // edge cases
42 // 0 - 0 = 0
43 // MIN - MIN = 0
44 // MAX - MAX = 0
45 // 0 - MIN overflow
46 // 0 - MAX = MIN+1
47 // MIN - 0 = MIN
48 // MAX - 0 = MAX
49 // MIN - MAX overflow
50 // MAX - MIN overflow
51 try test__subosi4(0, 0);
52 try test__subosi4(min, min);
53 try test__subosi4(max, max);
54 try test__subosi4(0, min);
55 try test__subosi4(0, max);
56 try test__subosi4(min, 0);
57 try test__subosi4(max, 0);
58 try test__subosi4(min, max);
59 try test__subosi4(max, min);
60
61 // derived edge cases
62 // MIN+1 - MIN = 1
63 // MAX-1 - MAX = -1
64 // 1 - MIN overflow
65 // -1 - MIN = MAX
66 // -1 - MAX = MIN
67 // +1 - MAX = MIN+2
68 // MIN - 1 overflow
69 // MIN - -1 = MIN+1
70 // MAX - 1 = MAX-1
71 // MAX - -1 overflow
72 try test__subosi4(min + 1, min);
73 try test__subosi4(max - 1, max);
74 try test__subosi4(1, min);
75 try test__subosi4(-1, min);
76 try test__subosi4(-1, max);
77 try test__subosi4(1, max);
78 try test__subosi4(min, 1);
79 try test__subosi4(min, -1);
80 try test__subosi4(max, -1);
81 try test__subosi4(max, 1);
82}
lib/compiler_rt/suboti4_test.zig deleted-84
...@@ -1,84 +0,0 @@
1const subo = @import("subo.zig");
2const builtin = @import("builtin");
3const std = @import("std");
4const testing = std.testing;
5const math = std.math;
6
7fn test__suboti4(a: i128, b: i128) !void {
8 var result_ov: c_int = undefined;
9 var expected_ov: c_int = undefined;
10 const result = subo.__suboti4(a, b, &result_ov);
11 const expected: i128 = simple_suboti4(a, b, &expected_ov);
12 try testing.expectEqual(expected, result);
13 try testing.expectEqual(expected_ov, result_ov);
14}
15
16// 2 cases on evaluating `a-b`:
17// 1. `a-b` may underflow, iff b>0 && a<0 and a-b < min <=> a<min+b
18// 2. `a-b` may overflow, iff b<0 && a>0 and a-b > max <=> a>max+b
19// `-b` evaluation may overflow, iff b==min, but this is handled by the hardware
20pub fn simple_suboti4(a: i128, b: i128, overflow: *c_int) i128 {
21 overflow.* = 0;
22 const min: i128 = math.minInt(i128);
23 const max: i128 = math.maxInt(i128);
24 if (((b > 0) and (a < min + b)) or
25 ((b < 0) and (a > max + b)))
26 overflow.* = 1;
27 return a -% b;
28}
29
30test "suboti3" {
31 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
32
33 const min: i128 = math.minInt(i128);
34 const max: i128 = math.maxInt(i128);
35 var i: i128 = 1;
36 while (i < max) : (i *|= 2) {
37 try test__suboti4(i, i);
38 try test__suboti4(-i, -i);
39 try test__suboti4(i, -i);
40 try test__suboti4(-i, i);
41 }
42
43 // edge cases
44 // 0 - 0 = 0
45 // MIN - MIN = 0
46 // MAX - MAX = 0
47 // 0 - MIN overflow
48 // 0 - MAX = MIN+1
49 // MIN - 0 = MIN
50 // MAX - 0 = MAX
51 // MIN - MAX overflow
52 // MAX - MIN overflow
53 try test__suboti4(0, 0);
54 try test__suboti4(min, min);
55 try test__suboti4(max, max);
56 try test__suboti4(0, min);
57 try test__suboti4(0, max);
58 try test__suboti4(min, 0);
59 try test__suboti4(max, 0);
60 try test__suboti4(min, max);
61 try test__suboti4(max, min);
62
63 // derived edge cases
64 // MIN+1 - MIN = 1
65 // MAX-1 - MAX = -1
66 // 1 - MIN overflow
67 // -1 - MIN = MAX
68 // -1 - MAX = MIN
69 // +1 - MAX = MIN+2
70 // MIN - 1 overflow
71 // MIN - -1 = MIN+1
72 // MAX - 1 = MAX-1
73 // MAX - -1 overflow
74 try test__suboti4(min + 1, min);
75 try test__suboti4(max - 1, max);
76 try test__suboti4(1, min);
77 try test__suboti4(-1, min);
78 try test__suboti4(-1, max);
79 try test__suboti4(1, max);
80 try test__suboti4(min, 1);
81 try test__suboti4(min, -1);
82 try test__suboti4(max, -1);
83 try test__suboti4(max, 1);
84}
lib/compiler_rt/subvdi3.zig+4-4
...@@ -1,4 +1,3 @@...@@ -1,4 +1,3 @@
1const subv = @import("subo.zig");
2const common = @import("./common.zig");1const common = @import("./common.zig");
3const testing = @import("std").testing;2const testing = @import("std").testing;
43
...@@ -9,9 +8,10 @@ comptime {...@@ -9,9 +8,10 @@ comptime {
9}8}
109
11pub fn __subvdi3(a: i64, b: i64) callconv(.c) i64 {10pub fn __subvdi3(a: i64, b: i64) callconv(.c) i64 {
12 var overflow: c_int = 0;11 const sum = a -% b;
13 const sum = subv.__subodi4(a, b, &overflow);12 // Overflow occurred iff the operands have opposite signs, and the sign of the
14 if (overflow != 0) @panic("compiler-rt: integer overflow");13 // sum is the opposite of the lhs sign.
14 if (((a ^ b) & (sum ^ a)) < 0) @panic("compiler-rt: integer overflow");
15 return sum;15 return sum;
16}16}
1717
lib/compiler_rt/subvsi3.zig+4-4
...@@ -1,4 +1,3 @@...@@ -1,4 +1,3 @@
1const subv = @import("subo.zig");
2const common = @import("./common.zig");1const common = @import("./common.zig");
3const testing = @import("std").testing;2const testing = @import("std").testing;
43
...@@ -9,9 +8,10 @@ comptime {...@@ -9,9 +8,10 @@ comptime {
9}8}
109
11pub fn __subvsi3(a: i32, b: i32) callconv(.c) i32 {10pub fn __subvsi3(a: i32, b: i32) callconv(.c) i32 {
12 var overflow: c_int = 0;11 const sum = a -% b;
13 const sum = subv.__subosi4(a, b, &overflow);12 // Overflow occurred iff the operands have opposite signs, and the sign of the
14 if (overflow != 0) @panic("compiler-rt: integer overflow");13 // sum is the opposite of the lhs sign.
14 if (((a ^ b) & (sum ^ a)) < 0) @panic("compiler-rt: integer overflow");
15 return sum;15 return sum;
16}16}
1717