aboutsummaryrefslogtreecommitdiff
path: root/lib/compiler_rt
diff options
context:
space:
mode:
authorMatthew Lugg <mlugg@mlugg.co.uk>2025-11-12 23:14:02 +0000
committerGitHub <noreply@github.com>2025-11-12 23:14:02 +0000
commit181b25ce4fcebc32f6fdc7498148c0f5e131dda9 (patch)
treef5cfe981b1b158e8bac17cc3a3bc909ffb7b1aa1 /lib/compiler_rt
parentdfd7b7f2337d84ce660253a37079489f7780b055 (diff)
parent532aa3c5758f110eb7cf0992eb394088ab563899 (diff)
downloadzig-181b25ce4fcebc32f6fdc7498148c0f5e131dda9.tar.gz
zig-181b25ce4fcebc32f6fdc7498148c0f5e131dda9.zip
Merge pull request #25772 from mlugg/kill-dead-code
compiler: rewrite some legalizations, and remove a bunch of dead code
Diffstat (limited to 'lib/compiler_rt')
-rw-r--r--lib/compiler_rt/addo.zig46
-rw-r--r--lib/compiler_rt/addodi4_test.zig77
-rw-r--r--lib/compiler_rt/addosi4_test.zig78
-rw-r--r--lib/compiler_rt/addoti4_test.zig80
-rw-r--r--lib/compiler_rt/addvdi3.zig26
-rw-r--r--lib/compiler_rt/addvsi3.zig8
-rw-r--r--lib/compiler_rt/subo.zig47
-rw-r--r--lib/compiler_rt/subodi4_test.zig81
-rw-r--r--lib/compiler_rt/subosi4_test.zig82
-rw-r--r--lib/compiler_rt/suboti4_test.zig84
-rw-r--r--lib/compiler_rt/subvdi3.zig8
-rw-r--r--lib/compiler_rt/subvsi3.zig8
12 files changed, 38 insertions, 587 deletions
diff --git a/lib/compiler_rt/addo.zig b/lib/compiler_rt/addo.zig
deleted file mode 100644
index 610d620690..0000000000
--- a/lib/compiler_rt/addo.zig
+++ /dev/null
@@ -1,46 +0,0 @@
-const std = @import("std");
-const common = @import("./common.zig");
-pub const panic = @import("common.zig").panic;
-
-comptime {
- @export(&__addosi4, .{ .name = "__addosi4", .linkage = common.linkage, .visibility = common.visibility });
- @export(&__addodi4, .{ .name = "__addodi4", .linkage = common.linkage, .visibility = common.visibility });
- @export(&__addoti4, .{ .name = "__addoti4", .linkage = common.linkage, .visibility = common.visibility });
-}
-
-// addo - add overflow
-// * return a+%b.
-// * return if a+b overflows => 1 else => 0
-// - addoXi4_generic as default
-
-inline fn addoXi4_generic(comptime ST: type, a: ST, b: ST, overflow: *c_int) ST {
- @setRuntimeSafety(common.test_safety);
- overflow.* = 0;
- const sum: ST = a +% b;
- // Hackers Delight: section Overflow Detection, subsection Signed Add/Subtract
- // Let sum = a +% b == a + b + carry == wraparound addition.
- // Overflow in a+b+carry occurs, iff a and b have opposite signs
- // and the sign of a+b+carry is the same as a (or equivalently b).
- // Slower routine: res = ~(a ^ b) & ((sum ^ a)
- // Faster routine: res = (sum ^ a) & (sum ^ b)
- // Overflow occurred, iff (res < 0)
- if (((sum ^ a) & (sum ^ b)) < 0)
- overflow.* = 1;
- return sum;
-}
-
-pub fn __addosi4(a: i32, b: i32, overflow: *c_int) callconv(.c) i32 {
- return addoXi4_generic(i32, a, b, overflow);
-}
-pub fn __addodi4(a: i64, b: i64, overflow: *c_int) callconv(.c) i64 {
- return addoXi4_generic(i64, a, b, overflow);
-}
-pub fn __addoti4(a: i128, b: i128, overflow: *c_int) callconv(.c) i128 {
- return addoXi4_generic(i128, a, b, overflow);
-}
-
-test {
- _ = @import("addosi4_test.zig");
- _ = @import("addodi4_test.zig");
- _ = @import("addoti4_test.zig");
-}
diff --git a/lib/compiler_rt/addodi4_test.zig b/lib/compiler_rt/addodi4_test.zig
deleted file mode 100644
index 92f8e9c1f2..0000000000
--- a/lib/compiler_rt/addodi4_test.zig
+++ /dev/null
@@ -1,77 +0,0 @@
-const addv = @import("addo.zig");
-const std = @import("std");
-const testing = std.testing;
-const math = std.math;
-
-fn test__addodi4(a: i64, b: i64) !void {
- var result_ov: c_int = undefined;
- var expected_ov: c_int = undefined;
- const result = addv.__addodi4(a, b, &result_ov);
- const expected: i64 = simple_addodi4(a, b, &expected_ov);
- try testing.expectEqual(expected, result);
- try testing.expectEqual(expected_ov, result_ov);
-}
-
-fn simple_addodi4(a: i64, b: i64, overflow: *c_int) i64 {
- overflow.* = 0;
- const min: i64 = math.minInt(i64);
- const max: i64 = math.maxInt(i64);
- if (((a > 0) and (b > max - a)) or
- ((a < 0) and (b < min - a)))
- overflow.* = 1;
- return a +% b;
-}
-
-test "addodi4" {
- const min: i64 = math.minInt(i64);
- const max: i64 = math.maxInt(i64);
- var i: i64 = 1;
- while (i < max) : (i *|= 2) {
- try test__addodi4(i, i);
- try test__addodi4(-i, -i);
- try test__addodi4(i, -i);
- try test__addodi4(-i, i);
- }
-
- // edge cases
- // 0 + 0 = 0
- // MIN + MIN overflow
- // MAX + MAX overflow
- // 0 + MIN MIN
- // 0 + MAX MAX
- // MIN + 0 MIN
- // MAX + 0 MAX
- // MIN + MAX -1
- // MAX + MIN -1
- try test__addodi4(0, 0);
- try test__addodi4(min, min);
- try test__addodi4(max, max);
- try test__addodi4(0, min);
- try test__addodi4(0, max);
- try test__addodi4(min, 0);
- try test__addodi4(max, 0);
- try test__addodi4(min, max);
- try test__addodi4(max, min);
-
- // derived edge cases
- // MIN+1 + MIN overflow
- // MAX-1 + MAX overflow
- // 1 + MIN = MIN+1
- // -1 + MIN overflow
- // -1 + MAX = MAX-1
- // +1 + MAX overflow
- // MIN + 1 = MIN+1
- // MIN + -1 overflow
- // MAX + 1 overflow
- // MAX + -1 = MAX-1
- try test__addodi4(min + 1, min);
- try test__addodi4(max - 1, max);
- try test__addodi4(1, min);
- try test__addodi4(-1, min);
- try test__addodi4(-1, max);
- try test__addodi4(1, max);
- try test__addodi4(min, 1);
- try test__addodi4(min, -1);
- try test__addodi4(max, -1);
- try test__addodi4(max, 1);
-}
diff --git a/lib/compiler_rt/addosi4_test.zig b/lib/compiler_rt/addosi4_test.zig
deleted file mode 100644
index 3494909f50..0000000000
--- a/lib/compiler_rt/addosi4_test.zig
+++ /dev/null
@@ -1,78 +0,0 @@
-const addv = @import("addo.zig");
-const testing = @import("std").testing;
-
-fn test__addosi4(a: i32, b: i32) !void {
- var result_ov: c_int = undefined;
- var expected_ov: c_int = undefined;
- const result = addv.__addosi4(a, b, &result_ov);
- const expected: i32 = simple_addosi4(a, b, &expected_ov);
- try testing.expectEqual(expected, result);
- try testing.expectEqual(expected_ov, result_ov);
-}
-
-fn simple_addosi4(a: i32, b: i32, overflow: *c_int) i32 {
- overflow.* = 0;
- const min: i32 = -2147483648;
- const max: i32 = 2147483647;
- if (((a > 0) and (b > max - a)) or
- ((a < 0) and (b < min - a)))
- overflow.* = 1;
- return a +% b;
-}
-
-test "addosi4" {
- // -2^31 <= i32 <= 2^31-1
- // 2^31 = 2147483648
- // 2^31-1 = 2147483647
- const min: i32 = -2147483648;
- const max: i32 = 2147483647;
- var i: i32 = 1;
- while (i < max) : (i *|= 2) {
- try test__addosi4(i, i);
- try test__addosi4(-i, -i);
- try test__addosi4(i, -i);
- try test__addosi4(-i, i);
- }
-
- // edge cases
- // 0 + 0 = 0
- // MIN + MIN overflow
- // MAX + MAX overflow
- // 0 + MIN MIN
- // 0 + MAX MAX
- // MIN + 0 MIN
- // MAX + 0 MAX
- // MIN + MAX -1
- // MAX + MIN -1
- try test__addosi4(0, 0);
- try test__addosi4(min, min);
- try test__addosi4(max, max);
- try test__addosi4(0, min);
- try test__addosi4(0, max);
- try test__addosi4(min, 0);
- try test__addosi4(max, 0);
- try test__addosi4(min, max);
- try test__addosi4(max, min);
-
- // derived edge cases
- // MIN+1 + MIN overflow
- // MAX-1 + MAX overflow
- // 1 + MIN = MIN+1
- // -1 + MIN overflow
- // -1 + MAX = MAX-1
- // +1 + MAX overflow
- // MIN + 1 = MIN+1
- // MIN + -1 overflow
- // MAX + 1 overflow
- // MAX + -1 = MAX-1
- try test__addosi4(min + 1, min);
- try test__addosi4(max - 1, max);
- try test__addosi4(1, min);
- try test__addosi4(-1, min);
- try test__addosi4(-1, max);
- try test__addosi4(1, max);
- try test__addosi4(min, 1);
- try test__addosi4(min, -1);
- try test__addosi4(max, -1);
- try test__addosi4(max, 1);
-}
diff --git a/lib/compiler_rt/addoti4_test.zig b/lib/compiler_rt/addoti4_test.zig
deleted file mode 100644
index d031d1d428..0000000000
--- a/lib/compiler_rt/addoti4_test.zig
+++ /dev/null
@@ -1,80 +0,0 @@
-const addv = @import("addo.zig");
-const builtin = @import("builtin");
-const std = @import("std");
-const testing = std.testing;
-const math = std.math;
-
-fn test__addoti4(a: i128, b: i128) !void {
- var result_ov: c_int = undefined;
- var expected_ov: c_int = undefined;
- const result = addv.__addoti4(a, b, &result_ov);
- const expected: i128 = simple_addoti4(a, b, &expected_ov);
- try testing.expectEqual(expected, result);
- try testing.expectEqual(expected_ov, result_ov);
-}
-
-fn simple_addoti4(a: i128, b: i128, overflow: *c_int) i128 {
- overflow.* = 0;
- const min: i128 = math.minInt(i128);
- const max: i128 = math.maxInt(i128);
- if (((a > 0) and (b > max - a)) or
- ((a < 0) and (b < min - a)))
- overflow.* = 1;
- return a +% b;
-}
-
-test "addoti4" {
- if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
- const min: i128 = math.minInt(i128);
- const max: i128 = math.maxInt(i128);
- var i: i128 = 1;
- while (i < max) : (i *|= 2) {
- try test__addoti4(i, i);
- try test__addoti4(-i, -i);
- try test__addoti4(i, -i);
- try test__addoti4(-i, i);
- }
-
- // edge cases
- // 0 + 0 = 0
- // MIN + MIN overflow
- // MAX + MAX overflow
- // 0 + MIN MIN
- // 0 + MAX MAX
- // MIN + 0 MIN
- // MAX + 0 MAX
- // MIN + MAX -1
- // MAX + MIN -1
- try test__addoti4(0, 0);
- try test__addoti4(min, min);
- try test__addoti4(max, max);
- try test__addoti4(0, min);
- try test__addoti4(0, max);
- try test__addoti4(min, 0);
- try test__addoti4(max, 0);
- try test__addoti4(min, max);
- try test__addoti4(max, min);
-
- // derived edge cases
- // MIN+1 + MIN overflow
- // MAX-1 + MAX overflow
- // 1 + MIN = MIN+1
- // -1 + MIN overflow
- // -1 + MAX = MAX-1
- // +1 + MAX overflow
- // MIN + 1 = MIN+1
- // MIN + -1 overflow
- // MAX + 1 overflow
- // MAX + -1 = MAX-1
- try test__addoti4(min + 1, min);
- try test__addoti4(max - 1, max);
- try test__addoti4(1, min);
- try test__addoti4(-1, min);
- try test__addoti4(-1, max);
- try test__addoti4(1, max);
- try test__addoti4(min, 1);
- try test__addoti4(min, -1);
- try test__addoti4(max, -1);
- try test__addoti4(max, 1);
-}
diff --git a/lib/compiler_rt/addvdi3.zig b/lib/compiler_rt/addvdi3.zig
new file mode 100644
index 0000000000..03aa9b91c7
--- /dev/null
+++ b/lib/compiler_rt/addvdi3.zig
@@ -0,0 +1,26 @@
+const common = @import("./common.zig");
+const testing = @import("std").testing;
+
+pub const panic = common.panic;
+
+comptime {
+ @export(&__addvdi3, .{ .name = "__addvdi3", .linkage = common.linkage, .visibility = common.visibility });
+}
+
+pub fn __addvdi3(a: i64, b: i64) callconv(.c) i64 {
+ const sum = a +% b;
+ // Overflow occurred iff both operands have the same sign, and the sign of the sum does
+ // not match it. In other words, iff the sum sign is not the sign of either operand.
+ if (((sum ^ a) & (sum ^ b)) < 0) @panic("compiler-rt: integer overflow");
+ return sum;
+}
+
+test "addvdi3" {
+ // const min: i64 = -9223372036854775808
+ // const max: i64 = 9223372036854775807
+ // TODO write panic handler for testing panics
+ // try test__addvdi3(-9223372036854775808, -1, -1); // panic
+ // try test__addvdi3(9223372036854775807, 1, 1); // panic
+ try testing.expectEqual(-9223372036854775808, __addvdi3(-9223372036854775807, -1));
+ try testing.expectEqual(9223372036854775807, __addvdi3(9223372036854775806, 1));
+}
diff --git a/lib/compiler_rt/addvsi3.zig b/lib/compiler_rt/addvsi3.zig
index 04c19881bc..e688fdba58 100644
--- a/lib/compiler_rt/addvsi3.zig
+++ b/lib/compiler_rt/addvsi3.zig
@@ -1,4 +1,3 @@
-const addv = @import("addo.zig");
const common = @import("./common.zig");
const testing = @import("std").testing;
@@ -9,9 +8,10 @@ comptime {
}
pub fn __addvsi3(a: i32, b: i32) callconv(.c) i32 {
- var overflow: c_int = 0;
- const sum = addv.__addosi4(a, b, &overflow);
- if (overflow != 0) @panic("compiler-rt: integer overflow");
+ const sum = a +% b;
+ // Overflow occurred iff both operands have the same sign, and the sign of the sum does
+ // not match it. In other words, iff the sum sign is not the sign of either operand.
+ if (((sum ^ a) & (sum ^ b)) < 0) @panic("compiler-rt: integer overflow");
return sum;
}
diff --git a/lib/compiler_rt/subo.zig b/lib/compiler_rt/subo.zig
deleted file mode 100644
index b4fb8f7710..0000000000
--- a/lib/compiler_rt/subo.zig
+++ /dev/null
@@ -1,47 +0,0 @@
-//! subo - subtract overflow
-//! * return a-%b.
-//! * return if a-b overflows => 1 else => 0
-//! - suboXi4_generic as default
-
-const std = @import("std");
-const builtin = @import("builtin");
-const common = @import("common.zig");
-
-pub const panic = common.panic;
-
-comptime {
- @export(&__subosi4, .{ .name = "__subosi4", .linkage = common.linkage, .visibility = common.visibility });
- @export(&__subodi4, .{ .name = "__subodi4", .linkage = common.linkage, .visibility = common.visibility });
- @export(&__suboti4, .{ .name = "__suboti4", .linkage = common.linkage, .visibility = common.visibility });
-}
-
-pub fn __subosi4(a: i32, b: i32, overflow: *c_int) callconv(.c) i32 {
- return suboXi4_generic(i32, a, b, overflow);
-}
-pub fn __subodi4(a: i64, b: i64, overflow: *c_int) callconv(.c) i64 {
- return suboXi4_generic(i64, a, b, overflow);
-}
-pub fn __suboti4(a: i128, b: i128, overflow: *c_int) callconv(.c) i128 {
- return suboXi4_generic(i128, a, b, overflow);
-}
-
-inline fn suboXi4_generic(comptime ST: type, a: ST, b: ST, overflow: *c_int) ST {
- overflow.* = 0;
- const sum: ST = a -% b;
- // Hackers Delight: section Overflow Detection, subsection Signed Add/Subtract
- // Let sum = a -% b == a - b - carry == wraparound subtraction.
- // Overflow in a-b-carry occurs, iff a and b have opposite signs
- // and the sign of a-b-carry is opposite of a (or equivalently same as b).
- // Faster routine: res = (a ^ b) & (sum ^ a)
- // Slower routine: res = (sum^a) & ~(sum^b)
- // Overflow occurred, iff (res < 0)
- if (((a ^ b) & (sum ^ a)) < 0)
- overflow.* = 1;
- return sum;
-}
-
-test {
- _ = @import("subosi4_test.zig");
- _ = @import("subodi4_test.zig");
- _ = @import("suboti4_test.zig");
-}
diff --git a/lib/compiler_rt/subodi4_test.zig b/lib/compiler_rt/subodi4_test.zig
deleted file mode 100644
index 2dd717e14b..0000000000
--- a/lib/compiler_rt/subodi4_test.zig
+++ /dev/null
@@ -1,81 +0,0 @@
-const subo = @import("subo.zig");
-const std = @import("std");
-const testing = std.testing;
-const math = std.math;
-
-fn test__subodi4(a: i64, b: i64) !void {
- var result_ov: c_int = undefined;
- var expected_ov: c_int = undefined;
- const result = subo.__subodi4(a, b, &result_ov);
- const expected: i64 = simple_subodi4(a, b, &expected_ov);
- try testing.expectEqual(expected, result);
- try testing.expectEqual(expected_ov, result_ov);
-}
-
-// 2 cases on evaluating `a-b`:
-// 1. `a-b` may underflow, iff b>0 && a<0 and a-b < min <=> a<min+b
-// 2. `a-b` may overflow, iff b<0 && a>0 and a-b > max <=> a>max+b
-// `-b` evaluation may overflow, iff b==min, but this is handled by the hardware
-pub fn simple_subodi4(a: i64, b: i64, overflow: *c_int) i64 {
- overflow.* = 0;
- const min: i64 = math.minInt(i64);
- const max: i64 = math.maxInt(i64);
- if (((b > 0) and (a < min + b)) or
- ((b < 0) and (a > max + b)))
- overflow.* = 1;
- return a -% b;
-}
-
-test "subodi3" {
- const min: i64 = math.minInt(i64);
- const max: i64 = math.maxInt(i64);
- var i: i64 = 1;
- while (i < max) : (i *|= 2) {
- try test__subodi4(i, i);
- try test__subodi4(-i, -i);
- try test__subodi4(i, -i);
- try test__subodi4(-i, i);
- }
-
- // edge cases
- // 0 - 0 = 0
- // MIN - MIN = 0
- // MAX - MAX = 0
- // 0 - MIN overflow
- // 0 - MAX = MIN+1
- // MIN - 0 = MIN
- // MAX - 0 = MAX
- // MIN - MAX overflow
- // MAX - MIN overflow
- try test__subodi4(0, 0);
- try test__subodi4(min, min);
- try test__subodi4(max, max);
- try test__subodi4(0, min);
- try test__subodi4(0, max);
- try test__subodi4(min, 0);
- try test__subodi4(max, 0);
- try test__subodi4(min, max);
- try test__subodi4(max, min);
-
- // derived edge cases
- // MIN+1 - MIN = 1
- // MAX-1 - MAX = -1
- // 1 - MIN overflow
- // -1 - MIN = MAX
- // -1 - MAX = MIN
- // +1 - MAX = MIN+2
- // MIN - 1 overflow
- // MIN - -1 = MIN+1
- // MAX - 1 = MAX-1
- // MAX - -1 overflow
- try test__subodi4(min + 1, min);
- try test__subodi4(max - 1, max);
- try test__subodi4(1, min);
- try test__subodi4(-1, min);
- try test__subodi4(-1, max);
- try test__subodi4(1, max);
- try test__subodi4(min, 1);
- try test__subodi4(min, -1);
- try test__subodi4(max, -1);
- try test__subodi4(max, 1);
-}
diff --git a/lib/compiler_rt/subosi4_test.zig b/lib/compiler_rt/subosi4_test.zig
deleted file mode 100644
index 8644e8100e..0000000000
--- a/lib/compiler_rt/subosi4_test.zig
+++ /dev/null
@@ -1,82 +0,0 @@
-const subo = @import("subo.zig");
-const testing = @import("std").testing;
-
-fn test__subosi4(a: i32, b: i32) !void {
- var result_ov: c_int = undefined;
- var expected_ov: c_int = undefined;
- const result = subo.__subosi4(a, b, &result_ov);
- const expected: i32 = simple_subosi4(a, b, &expected_ov);
- try testing.expectEqual(expected, result);
- try testing.expectEqual(expected_ov, result_ov);
-}
-
-// 2 cases on evaluating `a-b`:
-// 1. `a-b` may underflow, iff b>0 && a<0 and a-b < min <=> a<min+b
-// 2. `a-b` may overflow, iff b<0 && a>0 and a-b > max <=> a>max+b
-// `-b` evaluation may overflow, iff b==min, but this is handled by the hardware
-pub fn simple_subosi4(a: i32, b: i32, overflow: *c_int) i32 {
- overflow.* = 0;
- const min: i32 = -2147483648;
- const max: i32 = 2147483647;
- if (((b > 0) and (a < min + b)) or
- ((b < 0) and (a > max + b)))
- overflow.* = 1;
- return a -% b;
-}
-
-test "subosi3" {
- // -2^31 <= i32 <= 2^31-1
- // 2^31 = 2147483648
- // 2^31-1 = 2147483647
- const min: i32 = -2147483648;
- const max: i32 = 2147483647;
- var i: i32 = 1;
- while (i < max) : (i *|= 2) {
- try test__subosi4(i, i);
- try test__subosi4(-i, -i);
- try test__subosi4(i, -i);
- try test__subosi4(-i, i);
- }
-
- // edge cases
- // 0 - 0 = 0
- // MIN - MIN = 0
- // MAX - MAX = 0
- // 0 - MIN overflow
- // 0 - MAX = MIN+1
- // MIN - 0 = MIN
- // MAX - 0 = MAX
- // MIN - MAX overflow
- // MAX - MIN overflow
- try test__subosi4(0, 0);
- try test__subosi4(min, min);
- try test__subosi4(max, max);
- try test__subosi4(0, min);
- try test__subosi4(0, max);
- try test__subosi4(min, 0);
- try test__subosi4(max, 0);
- try test__subosi4(min, max);
- try test__subosi4(max, min);
-
- // derived edge cases
- // MIN+1 - MIN = 1
- // MAX-1 - MAX = -1
- // 1 - MIN overflow
- // -1 - MIN = MAX
- // -1 - MAX = MIN
- // +1 - MAX = MIN+2
- // MIN - 1 overflow
- // MIN - -1 = MIN+1
- // MAX - 1 = MAX-1
- // MAX - -1 overflow
- try test__subosi4(min + 1, min);
- try test__subosi4(max - 1, max);
- try test__subosi4(1, min);
- try test__subosi4(-1, min);
- try test__subosi4(-1, max);
- try test__subosi4(1, max);
- try test__subosi4(min, 1);
- try test__subosi4(min, -1);
- try test__subosi4(max, -1);
- try test__subosi4(max, 1);
-}
diff --git a/lib/compiler_rt/suboti4_test.zig b/lib/compiler_rt/suboti4_test.zig
deleted file mode 100644
index 65018bc966..0000000000
--- a/lib/compiler_rt/suboti4_test.zig
+++ /dev/null
@@ -1,84 +0,0 @@
-const subo = @import("subo.zig");
-const builtin = @import("builtin");
-const std = @import("std");
-const testing = std.testing;
-const math = std.math;
-
-fn test__suboti4(a: i128, b: i128) !void {
- var result_ov: c_int = undefined;
- var expected_ov: c_int = undefined;
- const result = subo.__suboti4(a, b, &result_ov);
- const expected: i128 = simple_suboti4(a, b, &expected_ov);
- try testing.expectEqual(expected, result);
- try testing.expectEqual(expected_ov, result_ov);
-}
-
-// 2 cases on evaluating `a-b`:
-// 1. `a-b` may underflow, iff b>0 && a<0 and a-b < min <=> a<min+b
-// 2. `a-b` may overflow, iff b<0 && a>0 and a-b > max <=> a>max+b
-// `-b` evaluation may overflow, iff b==min, but this is handled by the hardware
-pub fn simple_suboti4(a: i128, b: i128, overflow: *c_int) i128 {
- overflow.* = 0;
- const min: i128 = math.minInt(i128);
- const max: i128 = math.maxInt(i128);
- if (((b > 0) and (a < min + b)) or
- ((b < 0) and (a > max + b)))
- overflow.* = 1;
- return a -% b;
-}
-
-test "suboti3" {
- if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
-
- const min: i128 = math.minInt(i128);
- const max: i128 = math.maxInt(i128);
- var i: i128 = 1;
- while (i < max) : (i *|= 2) {
- try test__suboti4(i, i);
- try test__suboti4(-i, -i);
- try test__suboti4(i, -i);
- try test__suboti4(-i, i);
- }
-
- // edge cases
- // 0 - 0 = 0
- // MIN - MIN = 0
- // MAX - MAX = 0
- // 0 - MIN overflow
- // 0 - MAX = MIN+1
- // MIN - 0 = MIN
- // MAX - 0 = MAX
- // MIN - MAX overflow
- // MAX - MIN overflow
- try test__suboti4(0, 0);
- try test__suboti4(min, min);
- try test__suboti4(max, max);
- try test__suboti4(0, min);
- try test__suboti4(0, max);
- try test__suboti4(min, 0);
- try test__suboti4(max, 0);
- try test__suboti4(min, max);
- try test__suboti4(max, min);
-
- // derived edge cases
- // MIN+1 - MIN = 1
- // MAX-1 - MAX = -1
- // 1 - MIN overflow
- // -1 - MIN = MAX
- // -1 - MAX = MIN
- // +1 - MAX = MIN+2
- // MIN - 1 overflow
- // MIN - -1 = MIN+1
- // MAX - 1 = MAX-1
- // MAX - -1 overflow
- try test__suboti4(min + 1, min);
- try test__suboti4(max - 1, max);
- try test__suboti4(1, min);
- try test__suboti4(-1, min);
- try test__suboti4(-1, max);
- try test__suboti4(1, max);
- try test__suboti4(min, 1);
- try test__suboti4(min, -1);
- try test__suboti4(max, -1);
- try test__suboti4(max, 1);
-}
diff --git a/lib/compiler_rt/subvdi3.zig b/lib/compiler_rt/subvdi3.zig
index 8248e93022..a34deb2da1 100644
--- a/lib/compiler_rt/subvdi3.zig
+++ b/lib/compiler_rt/subvdi3.zig
@@ -1,4 +1,3 @@
-const subv = @import("subo.zig");
const common = @import("./common.zig");
const testing = @import("std").testing;
@@ -9,9 +8,10 @@ comptime {
}
pub fn __subvdi3(a: i64, b: i64) callconv(.c) i64 {
- var overflow: c_int = 0;
- const sum = subv.__subodi4(a, b, &overflow);
- if (overflow != 0) @panic("compiler-rt: integer overflow");
+ const sum = a -% b;
+ // Overflow occurred iff the operands have opposite signs, and the sign of the
+ // sum is the opposite of the lhs sign.
+ if (((a ^ b) & (sum ^ a)) < 0) @panic("compiler-rt: integer overflow");
return sum;
}
diff --git a/lib/compiler_rt/subvsi3.zig b/lib/compiler_rt/subvsi3.zig
index 8a2ea6c6a6..c524a3a634 100644
--- a/lib/compiler_rt/subvsi3.zig
+++ b/lib/compiler_rt/subvsi3.zig
@@ -1,4 +1,3 @@
-const subv = @import("subo.zig");
const common = @import("./common.zig");
const testing = @import("std").testing;
@@ -9,9 +8,10 @@ comptime {
}
pub fn __subvsi3(a: i32, b: i32) callconv(.c) i32 {
- var overflow: c_int = 0;
- const sum = subv.__subosi4(a, b, &overflow);
- if (overflow != 0) @panic("compiler-rt: integer overflow");
+ const sum = a -% b;
+ // Overflow occurred iff the operands have opposite signs, and the sign of the
+ // sum is the opposite of the lhs sign.
+ if (((a ^ b) & (sum ^ a)) < 0) @panic("compiler-rt: integer overflow");
return sum;
}