authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-11-23 15:02:40+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-11-26 18:05:27+02:00
log72fa8d4880613d88f9f29dd78012b7253729bac7
treed9a84bce86501001b27cb5d31f0a596a3362f7b8
parent5b9d0a446af4e74c9f915a34b39de83d9b2335f9

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

2 files changed, 34 insertions(+), 25 deletions(-)

src/Sema.zig+1-9
......@@ -13468,7 +13468,6 @@ fn zirOverflowArithmetic(
1346813468 const maybe_rhs_val = try sema.resolveMaybeUndefVal(rhs);
1346913469
1347013470 const tuple_ty = try sema.overflowArithmeticTupleType(dest_ty);
13471 const ov_ty = tuple_ty.tupleFields().types[1];
1347213471 // TODO: Remove and use `ov_ty` instead.
1347313472 // This is a temporary type used until overflow arithmetic properly returns `u1` instead of `bool`.
1347413473 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(
1361913618 try sema.storePtr2(block, src, ptr, ptr_src, wrapped, src, .store);
1362013619
1362113620 const overflow_bit = try sema.tupleFieldValByIndex(block, src, tuple, 1, tuple_ty);
13622 const zero_ov_val = if (dest_ty.zigTypeTag() == .Vector) try Value.Tag.repeated.create(sema.arena, Value.zero) else Value.zero;
13623 const zero_ov = try sema.addConstant(ov_ty, zero_ov_val);
13624
13625 const overflowed_inst = if (dest_ty.zigTypeTag() == .Vector)
13626 block.addCmpVector(overflow_bit, .zero, .neq, try sema.addType(ov_ty))
13627 else
13628 block.addBinOp(.cmp_neq, overflow_bit, zero_ov);
13629 return overflowed_inst;
13621 return block.addBitCast(overflowed_ty, overflow_bit);
1363013622 };
1363113623
1363213624 try sema.storePtr2(block, src, ptr, ptr_src, result.wrapped, src, .store);
test/behavior/vector.zig+33-16
......@@ -977,27 +977,35 @@ test "@addWithOverflow" {
977977 fn doTheTest() !void {
978978 {
979979 var result: @Vector(4, u8) = undefined;
980 var overflow = @addWithOverflow(@Vector(4, u8), @Vector(4, u8){ 250, 250, 250, 250 }, @Vector(4, u8){ 0, 5, 6, 10 }, &result);
980 var lhs = @Vector(4, u8){ 250, 250, 250, 250 };
981 var rhs = @Vector(4, u8){ 0, 5, 6, 10 };
982 var overflow = @addWithOverflow(@Vector(4, u8), lhs, rhs, &result);
981983 var expected: @Vector(4, bool) = .{ false, false, true, true };
982 try expect(mem.eql(bool, &@as([4]bool, overflow), &@as([4]bool, expected)));
984 try expectEqual(expected, overflow);
983985 }
984986 {
985987 var result: @Vector(4, i8) = undefined;
986 var overflow = @addWithOverflow(@Vector(4, i8), @Vector(4, i8){ -125, -125, 125, 125 }, @Vector(4, i8){ -3, -4, 2, 3 }, &result);
988 var lhs = @Vector(4, i8){ -125, -125, 125, 125 };
989 var rhs = @Vector(4, i8){ -3, -4, 2, 3 };
990 var overflow = @addWithOverflow(@Vector(4, i8), lhs, rhs, &result);
987991 var expected: @Vector(4, bool) = .{ false, true, false, true };
988 try expect(mem.eql(bool, &@as([4]bool, overflow), &@as([4]bool, expected)));
992 try expectEqual(expected, overflow);
989993 }
990994 {
991995 var result: @Vector(4, u1) = undefined;
992 var overflow = @addWithOverflow(@Vector(4, u1), @Vector(4, u1){ 0, 0, 1, 1 }, @Vector(4, u1){ 0, 1, 0, 1 }, &result);
996 var lhs = @Vector(4, u1){ 0, 0, 1, 1 };
997 var rhs = @Vector(4, u1){ 0, 1, 0, 1 };
998 var overflow = @addWithOverflow(@Vector(4, u1), lhs, rhs, &result);
993999 var expected: @Vector(4, bool) = .{ false, false, false, true };
994 try expect(mem.eql(bool, &@as([4]bool, overflow), &@as([4]bool, expected)));
1000 try expectEqual(expected, overflow);
9951001 }
9961002 {
9971003 var result: @Vector(4, u0) = undefined;
998 var overflow = @addWithOverflow(@Vector(4, u0), @Vector(4, u0){ 0, 0, 0, 0 }, @Vector(4, u0){ 0, 0, 0, 0 }, &result);
1004 var lhs = @Vector(4, u0){ 0, 0, 0, 0 };
1005 var rhs = @Vector(4, u0){ 0, 0, 0, 0 };
1006 var overflow = @addWithOverflow(@Vector(4, u0), lhs, rhs, &result);
9991007 var expected: @Vector(4, bool) = .{ false, false, false, false };
1000 try expect(mem.eql(bool, &@as([4]bool, overflow), &@as([4]bool, expected)));
1008 try expectEqual(expected, overflow);
10011009 }
10021010 }
10031011 };
......@@ -1019,15 +1027,19 @@ test "@subWithOverflow" {
10191027 fn doTheTest() !void {
10201028 {
10211029 var result: @Vector(2, u8) = undefined;
1022 var overflow = @subWithOverflow(@Vector(2, u8), @Vector(2, u8){ 5, 5 }, @Vector(2, u8){ 5, 6 }, &result);
1030 var lhs = @Vector(2, u8){ 5, 5 };
1031 var rhs = @Vector(2, u8){ 5, 6 };
1032 var overflow = @subWithOverflow(@Vector(2, u8), lhs, rhs, &result);
10231033 var expected: @Vector(2, bool) = .{ false, true };
1024 try expect(mem.eql(bool, &@as([2]bool, overflow), &@as([2]bool, expected)));
1034 try expectEqual(expected, overflow);
10251035 }
10261036 {
10271037 var result: @Vector(4, i8) = undefined;
1028 var overflow = @subWithOverflow(@Vector(4, i8), @Vector(4, i8){ -120, -120, 120, 120 }, @Vector(4, i8){ 8, 9, -7, -8 }, &result);
1038 var lhs = @Vector(4, i8){ -120, -120, 120, 120 };
1039 var rhs = @Vector(4, i8){ 8, 9, -7, -8 };
1040 var overflow = @subWithOverflow(@Vector(4, i8), lhs, rhs, &result);
10291041 var expected: @Vector(4, bool) = .{ false, true, false, true };
1030 try expect(mem.eql(bool, &@as([4]bool, overflow), &@as([4]bool, expected)));
1042 try expectEqual(expected, overflow);
10311043 }
10321044 }
10331045 };
......@@ -1048,9 +1060,11 @@ test "@mulWithOverflow" {
10481060 const S = struct {
10491061 fn doTheTest() !void {
10501062 var result: @Vector(4, u8) = undefined;
1051 var overflow = @mulWithOverflow(@Vector(4, u8), @Vector(4, u8){ 10, 10, 10, 10 }, @Vector(4, u8){ 25, 26, 0, 30 }, &result);
1063 var lhs = @Vector(4, u8){ 10, 10, 10, 10 };
1064 var rhs = @Vector(4, u8){ 25, 26, 0, 30 };
1065 var overflow = @mulWithOverflow(@Vector(4, u8), lhs, rhs, &result);
10521066 var expected: @Vector(4, bool) = .{ false, true, false, true };
1053 try expect(mem.eql(bool, &@as([4]bool, overflow), &@as([4]bool, expected)));
1067 try expectEqual(expected, overflow);
10541068 }
10551069 };
10561070 try S.doTheTest();
......@@ -1062,6 +1076,7 @@ test "@shlWithOverflow" {
10621076 // stage1 doesn't support vector args
10631077 return error.SkipZigTest;
10641078 }
1079 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
10651080 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
10661081 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
10671082 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
......@@ -1070,9 +1085,11 @@ test "@shlWithOverflow" {
10701085 const S = struct {
10711086 fn doTheTest() !void {
10721087 var result: @Vector(4, u8) = undefined;
1073 var overflow = @shlWithOverflow(@Vector(4, u8), @Vector(4, u8){ 0, 1, 8, 255 }, @Vector(4, u3){ 7, 7, 7, 7 }, &result);
1088 var lhs = @Vector(4, u8){ 0, 1, 8, 255 };
1089 var rhs = @Vector(4, u3){ 7, 7, 7, 7 };
1090 var overflow = @shlWithOverflow(@Vector(4, u8), lhs, rhs, &result);
10741091 var expected: @Vector(4, bool) = .{ false, false, true, true };
1075 try expect(mem.eql(bool, &@as([4]bool, overflow), &@as([4]bool, expected)));
1092 try expectEqual(expected, overflow);
10761093 }
10771094 };
10781095 try S.doTheTest();