From 72fa8d4880613d88f9f29dd78012b7253729bac7 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Wed, 23 Nov 2022 15:02:40 +0200 Subject: [PATCH] Sema: fix overflow arithmetic with runtime vectors It should return a a vector of bools for compatibility with scalar operands and stage1 until #10248 can be implemented. Closes #13201 --- src/Sema.zig | 10 +------- test/behavior/vector.zig | 49 +++++++++++++++++++++++++++------------- 2 files changed, 34 insertions(+), 25 deletions(-) diff --git a/src/Sema.zig b/src/Sema.zig index 0a28d2d7d0..24faa946c4 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -13468,7 +13468,6 @@ fn zirOverflowArithmetic( const maybe_rhs_val = try sema.resolveMaybeUndefVal(rhs); const tuple_ty = try sema.overflowArithmeticTupleType(dest_ty); - const ov_ty = tuple_ty.tupleFields().types[1]; // TODO: Remove and use `ov_ty` instead. // This is a temporary type used until overflow arithmetic properly returns `u1` instead of `bool`. const overflowed_ty = if (dest_ty.zigTypeTag() == .Vector) try Type.vector(sema.arena, dest_ty.vectorLen(), Type.bool) else Type.bool; @@ -13619,14 +13618,7 @@ fn zirOverflowArithmetic( try sema.storePtr2(block, src, ptr, ptr_src, wrapped, src, .store); const overflow_bit = try sema.tupleFieldValByIndex(block, src, tuple, 1, tuple_ty); - const zero_ov_val = if (dest_ty.zigTypeTag() == .Vector) try Value.Tag.repeated.create(sema.arena, Value.zero) else Value.zero; - const zero_ov = try sema.addConstant(ov_ty, zero_ov_val); - - const overflowed_inst = if (dest_ty.zigTypeTag() == .Vector) - block.addCmpVector(overflow_bit, .zero, .neq, try sema.addType(ov_ty)) - else - block.addBinOp(.cmp_neq, overflow_bit, zero_ov); - return overflowed_inst; + return block.addBitCast(overflowed_ty, overflow_bit); }; try sema.storePtr2(block, src, ptr, ptr_src, result.wrapped, src, .store); diff --git a/test/behavior/vector.zig b/test/behavior/vector.zig index e756264418..30dd563abe 100644 --- a/test/behavior/vector.zig +++ b/test/behavior/vector.zig @@ -977,27 +977,35 @@ test "@addWithOverflow" { fn doTheTest() !void { { var result: @Vector(4, u8) = undefined; - var overflow = @addWithOverflow(@Vector(4, u8), @Vector(4, u8){ 250, 250, 250, 250 }, @Vector(4, u8){ 0, 5, 6, 10 }, &result); + var lhs = @Vector(4, u8){ 250, 250, 250, 250 }; + var rhs = @Vector(4, u8){ 0, 5, 6, 10 }; + var overflow = @addWithOverflow(@Vector(4, u8), lhs, rhs, &result); var expected: @Vector(4, bool) = .{ false, false, true, true }; - try expect(mem.eql(bool, &@as([4]bool, overflow), &@as([4]bool, expected))); + try expectEqual(expected, overflow); } { var result: @Vector(4, i8) = undefined; - var overflow = @addWithOverflow(@Vector(4, i8), @Vector(4, i8){ -125, -125, 125, 125 }, @Vector(4, i8){ -3, -4, 2, 3 }, &result); + var lhs = @Vector(4, i8){ -125, -125, 125, 125 }; + var rhs = @Vector(4, i8){ -3, -4, 2, 3 }; + var overflow = @addWithOverflow(@Vector(4, i8), lhs, rhs, &result); var expected: @Vector(4, bool) = .{ false, true, false, true }; - try expect(mem.eql(bool, &@as([4]bool, overflow), &@as([4]bool, expected))); + try expectEqual(expected, overflow); } { var result: @Vector(4, u1) = undefined; - var overflow = @addWithOverflow(@Vector(4, u1), @Vector(4, u1){ 0, 0, 1, 1 }, @Vector(4, u1){ 0, 1, 0, 1 }, &result); + var lhs = @Vector(4, u1){ 0, 0, 1, 1 }; + var rhs = @Vector(4, u1){ 0, 1, 0, 1 }; + var overflow = @addWithOverflow(@Vector(4, u1), lhs, rhs, &result); var expected: @Vector(4, bool) = .{ false, false, false, true }; - try expect(mem.eql(bool, &@as([4]bool, overflow), &@as([4]bool, expected))); + try expectEqual(expected, overflow); } { var result: @Vector(4, u0) = undefined; - var overflow = @addWithOverflow(@Vector(4, u0), @Vector(4, u0){ 0, 0, 0, 0 }, @Vector(4, u0){ 0, 0, 0, 0 }, &result); + var lhs = @Vector(4, u0){ 0, 0, 0, 0 }; + var rhs = @Vector(4, u0){ 0, 0, 0, 0 }; + var overflow = @addWithOverflow(@Vector(4, u0), lhs, rhs, &result); var expected: @Vector(4, bool) = .{ false, false, false, false }; - try expect(mem.eql(bool, &@as([4]bool, overflow), &@as([4]bool, expected))); + try expectEqual(expected, overflow); } } }; @@ -1019,15 +1027,19 @@ test "@subWithOverflow" { fn doTheTest() !void { { var result: @Vector(2, u8) = undefined; - var overflow = @subWithOverflow(@Vector(2, u8), @Vector(2, u8){ 5, 5 }, @Vector(2, u8){ 5, 6 }, &result); + var lhs = @Vector(2, u8){ 5, 5 }; + var rhs = @Vector(2, u8){ 5, 6 }; + var overflow = @subWithOverflow(@Vector(2, u8), lhs, rhs, &result); var expected: @Vector(2, bool) = .{ false, true }; - try expect(mem.eql(bool, &@as([2]bool, overflow), &@as([2]bool, expected))); + try expectEqual(expected, overflow); } { var result: @Vector(4, i8) = undefined; - var overflow = @subWithOverflow(@Vector(4, i8), @Vector(4, i8){ -120, -120, 120, 120 }, @Vector(4, i8){ 8, 9, -7, -8 }, &result); + var lhs = @Vector(4, i8){ -120, -120, 120, 120 }; + var rhs = @Vector(4, i8){ 8, 9, -7, -8 }; + var overflow = @subWithOverflow(@Vector(4, i8), lhs, rhs, &result); var expected: @Vector(4, bool) = .{ false, true, false, true }; - try expect(mem.eql(bool, &@as([4]bool, overflow), &@as([4]bool, expected))); + try expectEqual(expected, overflow); } } }; @@ -1048,9 +1060,11 @@ test "@mulWithOverflow" { const S = struct { fn doTheTest() !void { var result: @Vector(4, u8) = undefined; - var overflow = @mulWithOverflow(@Vector(4, u8), @Vector(4, u8){ 10, 10, 10, 10 }, @Vector(4, u8){ 25, 26, 0, 30 }, &result); + var lhs = @Vector(4, u8){ 10, 10, 10, 10 }; + var rhs = @Vector(4, u8){ 25, 26, 0, 30 }; + var overflow = @mulWithOverflow(@Vector(4, u8), lhs, rhs, &result); var expected: @Vector(4, bool) = .{ false, true, false, true }; - try expect(mem.eql(bool, &@as([4]bool, overflow), &@as([4]bool, expected))); + try expectEqual(expected, overflow); } }; try S.doTheTest(); @@ -1062,6 +1076,7 @@ test "@shlWithOverflow" { // stage1 doesn't support vector args return error.SkipZigTest; } + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO @@ -1070,9 +1085,11 @@ test "@shlWithOverflow" { const S = struct { fn doTheTest() !void { var result: @Vector(4, u8) = undefined; - var overflow = @shlWithOverflow(@Vector(4, u8), @Vector(4, u8){ 0, 1, 8, 255 }, @Vector(4, u3){ 7, 7, 7, 7 }, &result); + var lhs = @Vector(4, u8){ 0, 1, 8, 255 }; + var rhs = @Vector(4, u3){ 7, 7, 7, 7 }; + var overflow = @shlWithOverflow(@Vector(4, u8), lhs, rhs, &result); var expected: @Vector(4, bool) = .{ false, false, true, true }; - try expect(mem.eql(bool, &@as([4]bool, overflow), &@as([4]bool, expected))); + try expectEqual(expected, overflow); } }; try S.doTheTest();