| author | |
| committer | |
| log | 09ee89a89ce3e2a04021695e92893fc4e507c7e6 |
| tree | f4701b26dde7c674cb3ce236a1c1cbb5a9f6036c |
| parent | 3bb0056d60f64b1d2bfdb029d61c8a107afe212a |
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 { |
| 6875 | 6875 | }, |
| 6876 | 6876 | .big => .{ false, true }, |
| 6877 | 6877 | } else .{ false, false }; |
| 6878 | const operator_wraps = use_operator and scalar_ty.intInfo(zcu).bits == 8 * scalar_ty.abiSize(zcu); | |
| 6878 | 6879 | const op: union(enum) { |
| 6879 | 6880 | const Func = struct { operation: []const u8, info: BuiltinInfo = .none }; |
| 6880 | 6881 | builtin: Func, |
| ... | ... | @@ -6895,12 +6896,12 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6895 | 6896 | else => unreachable, |
| 6896 | 6897 | }, |
| 6897 | 6898 | .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 } }, | |
| 6899 | 6900 | .float => .{ .builtin = .{ .operation = "add" } }, |
| 6900 | 6901 | else => unreachable, |
| 6901 | 6902 | }, |
| 6902 | 6903 | .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 } }, | |
| 6904 | 6905 | .float => .{ .builtin = .{ .operation = "mul" } }, |
| 6905 | 6906 | else => unreachable, |
| 6906 | 6907 | }, |
test/behavior/vector.zig+2| ... | ... | @@ -969,6 +969,7 @@ test "vector reduce operation" { |
| 969 | 969 | try testReduce(.Add, [4]u64{ 9, 99, 999, 9999 }, @as(u64, 11106)); |
| 970 | 970 | try testReduce(.Add, [4]i128{ -9, -99, -999, -9999 }, @as(i128, -11106)); |
| 971 | 971 | try testReduce(.Add, [4]u128{ 9, 99, 999, 9999 }, @as(u128, 11106)); |
| 972 | try testReduce(.Add, [4]u7{ 100, 100, 0, 0 }, @as(u7, 72)); | |
| 972 | 973 | try testReduce(.Add, [4]f16{ -1.9, 5.1, -60.3, 100.0 }, @as(f16, 42.9)); |
| 973 | 974 | try testReduce(.Add, [4]f32{ -1.9, 5.1, -60.3, 100.0 }, @as(f32, 42.9)); |
| 974 | 975 | try testReduce(.Add, [4]f64{ -1.9, 5.1, -60.3, 100.0 }, @as(f64, 42.9)); |
| ... | ... | @@ -1017,6 +1018,7 @@ test "vector reduce operation" { |
| 1017 | 1018 | try testReduce(.Mul, [4]u64{ 9, 99, 999, 9999 }, @as(u64, 8900199891)); |
| 1018 | 1019 | try testReduce(.Mul, [4]i128{ -9, -99, -999, 9999 }, @as(i128, -8900199891)); |
| 1019 | 1020 | try testReduce(.Mul, [4]u128{ 9, 99, 999, 9999 }, @as(u128, 8900199891)); |
| 1021 | try testReduce(.Mul, [4]i3{ 3, 2, 1, 1 }, @as(i3, -2)); | |
| 1020 | 1022 | try testReduce(.Mul, [4]f16{ -1.9, 5.1, -60.3, 100.0 }, @as(f16, 58430.7)); |
| 1021 | 1023 | try testReduce(.Mul, [4]f32{ -1.9, 5.1, -60.3, 100.0 }, @as(f32, 58430.7)); |
| 1022 | 1024 | try testReduce(.Mul, [4]f64{ -1.9, 5.1, -60.3, 100.0 }, @as(f64, 58430.7)); |