authorgravatar for 124872+jedisct1@users.noreply.github.comFrank Denis <124872+jedisct1@users.noreply.github.com> 2026-10-23 15:38:13+02:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-10-25 01:47:12+02:00
log12584fac6c6798acfd4ff783a43ee37cbbaf9ef0
tree0cd9755c1335362565de75cc83da16565fb84ecb
parentdd0fbcc6027c19fdb195aa32101475f50a3fbc75
signature Signed by SSH key SHA256:7B/LJ7bpR1eX8aCXSr4mtd5M45VMPKcx9zY8e95b5QM

cbe: Fix @reduce(.Add) and @reduce(.Mul) with narrow integers

For integers up to 64 bits, the generated code used += and *=, but the C type might be bigger than the Zig type. For example, a sum or product of u1, u7 or i3 integers would end up out of range. Fix this by using zig_addw and zig_mulw if the integer bit width doesn't match the C type.

2 files changed, 5 insertions(+), 2 deletions(-)

src/codegen/c.zig+3-2
......@@ -6875,6 +6875,7 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
68756875 },
68766876 .big => .{ false, true },
68776877 } else .{ false, false };
6878 const operator_wraps = use_operator and scalar_ty.intInfo(zcu).bits == 8 * scalar_ty.abiSize(zcu);
68786879 const op: union(enum) {
68796880 const Func = struct { operation: []const u8, info: BuiltinInfo = .none };
68806881 builtin: Func,
......@@ -6895,12 +6896,12 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
68956896 else => unreachable,
68966897 },
68976898 .Add => switch (scalar_ty.zigTypeTag(zcu)) {
6898 .int => if (use_operator) .{ .infix = " += " } else .{ .builtin = .{ .operation = "addw", .info = .bits } },
6899 .int => if (operator_wraps) .{ .infix = " += " } else .{ .builtin = .{ .operation = "addw", .info = .bits } },
68996900 .float => .{ .builtin = .{ .operation = "add" } },
69006901 else => unreachable,
69016902 },
69026903 .Mul => switch (scalar_ty.zigTypeTag(zcu)) {
6903 .int => if (use_operator) .{ .infix = " *= " } else .{ .builtin = .{ .operation = "mulw", .info = .bits } },
6904 .int => if (operator_wraps) .{ .infix = " *= " } else .{ .builtin = .{ .operation = "mulw", .info = .bits } },
69046905 .float => .{ .builtin = .{ .operation = "mul" } },
69056906 else => unreachable,
69066907 },
test/behavior/vector.zig+2
......@@ -962,6 +962,7 @@ test "vector reduce operation" {
962962 try testReduce(.Add, [4]u64{ 9, 99, 999, 9999 }, @as(u64, 11106));
963963 try testReduce(.Add, [4]i128{ -9, -99, -999, -9999 }, @as(i128, -11106));
964964 try testReduce(.Add, [4]u128{ 9, 99, 999, 9999 }, @as(u128, 11106));
965 try testReduce(.Add, [4]u7{ 100, 100, 0, 0 }, @as(u7, 72));
965966 try testReduce(.Add, [4]f16{ -1.9, 5.1, -60.3, 100.0 }, @as(f16, 42.9));
966967 try testReduce(.Add, [4]f32{ -1.9, 5.1, -60.3, 100.0 }, @as(f32, 42.9));
967968 try testReduce(.Add, [4]f64{ -1.9, 5.1, -60.3, 100.0 }, @as(f64, 42.9));
......@@ -1010,6 +1011,7 @@ test "vector reduce operation" {
10101011 try testReduce(.Mul, [4]u64{ 9, 99, 999, 9999 }, @as(u64, 8900199891));
10111012 try testReduce(.Mul, [4]i128{ -9, -99, -999, 9999 }, @as(i128, -8900199891));
10121013 try testReduce(.Mul, [4]u128{ 9, 99, 999, 9999 }, @as(u128, 8900199891));
1014 try testReduce(.Mul, [4]i3{ 3, 2, 1, 1 }, @as(i3, -2));
10131015 try testReduce(.Mul, [4]f16{ -1.9, 5.1, -60.3, 100.0 }, @as(f16, 58430.7));
10141016 try testReduce(.Mul, [4]f32{ -1.9, 5.1, -60.3, 100.0 }, @as(f32, 58430.7));
10151017 try testReduce(.Mul, [4]f64{ -1.9, 5.1, -60.3, 100.0 }, @as(f64, 58430.7));