Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

stage2: Miscellaneous fixes to vector arithmetic and copy elision #13074

Merged
merged 6 commits into from
Nov 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/RangeSet.zig
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ pub fn add(
src: SwitchProngSrc,
) !?SwitchProngSrc {
for (self.ranges.items) |range| {
if (last.compare(.gte, range.first, ty, self.module) and
first.compare(.lte, range.last, ty, self.module))
if (last.compareAll(.gte, range.first, ty, self.module) and
first.compareAll(.lte, range.last, ty, self.module))
{
return range.src; // They overlap.
}
Expand All @@ -53,7 +53,7 @@ const LessThanContext = struct { ty: Type, module: *Module };

/// Assumes a and b do not overlap
fn lessThan(ctx: LessThanContext, a: Range, b: Range) bool {
return a.first.compare(.lt, b.first, ctx.ty, ctx.module);
return a.first.compareAll(.lt, b.first, ctx.ty, ctx.module);
}

pub fn spans(self: *RangeSet, first: Value, last: Value, ty: Type) !bool {
Expand Down
367 changes: 207 additions & 160 deletions src/Sema.zig

Large diffs are not rendered by default.

218 changes: 142 additions & 76 deletions src/codegen/llvm.zig

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions src/type.zig
Original file line number Diff line number Diff line change
Expand Up @@ -5463,13 +5463,13 @@ pub const Type = extern union {
}
const S = struct {
fn fieldWithRange(int_ty: Type, int_val: Value, end: usize, m: *Module) ?usize {
if (int_val.compareWithZero(.lt)) return null;
if (int_val.compareAllWithZero(.lt)) return null;
var end_payload: Value.Payload.U64 = .{
.base = .{ .tag = .int_u64 },
.data = end,
};
const end_val = Value.initPayload(&end_payload.base);
if (int_val.compare(.gte, end_val, int_ty, m)) return null;
if (int_val.compareAll(.gte, end_val, int_ty, m)) return null;
return @intCast(usize, int_val.toUnsignedInt(m.getTarget()));
}
};
Expand Down Expand Up @@ -6455,12 +6455,12 @@ pub const Type = extern union {
if (!d.mutable and d.pointee_type.eql(Type.u8, mod)) {
switch (d.size) {
.Slice => {
if (sent.compareWithZero(.eq)) {
if (sent.compareAllWithZero(.eq)) {
return Type.initTag(.const_slice_u8_sentinel_0);
}
},
.Many => {
if (sent.compareWithZero(.eq)) {
if (sent.compareAllWithZero(.eq)) {
return Type.initTag(.manyptr_const_u8_sentinel_0);
}
},
Expand Down
20 changes: 11 additions & 9 deletions src/value.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2005,8 +2005,8 @@ pub const Value = extern union {
}

/// Asserts the values are comparable. Both operands have type `ty`.
/// Vector results will be reduced with AND.
pub fn compare(lhs: Value, op: std.math.CompareOperator, rhs: Value, ty: Type, mod: *Module) bool {
/// For vectors, returns true if comparison is true for ALL elements.
pub fn compareAll(lhs: Value, op: std.math.CompareOperator, rhs: Value, ty: Type, mod: *Module) bool {
if (ty.zigTypeTag() == .Vector) {
var i: usize = 0;
while (i < ty.vectorLen()) : (i += 1) {
Expand Down Expand Up @@ -2035,21 +2035,23 @@ pub const Value = extern union {
}

/// Asserts the value is comparable.
/// Vector results will be reduced with AND.
pub fn compareWithZero(lhs: Value, op: std.math.CompareOperator) bool {
return compareWithZeroAdvanced(lhs, op, null) catch unreachable;
/// For vectors, returns true if comparison is true for ALL elements.
///
/// Note that `!compareAllWithZero(.eq, ...) != compareAllWithZero(.neq, ...)`
pub fn compareAllWithZero(lhs: Value, op: std.math.CompareOperator) bool {
return compareAllWithZeroAdvanced(lhs, op, null) catch unreachable;
}

pub fn compareWithZeroAdvanced(
pub fn compareAllWithZeroAdvanced(
lhs: Value,
op: std.math.CompareOperator,
sema_kit: ?Module.WipAnalysis,
) Module.CompileError!bool {
switch (lhs.tag()) {
.repeated => return lhs.castTag(.repeated).?.data.compareWithZeroAdvanced(op, sema_kit),
.repeated => return lhs.castTag(.repeated).?.data.compareAllWithZeroAdvanced(op, sema_kit),
.aggregate => {
for (lhs.castTag(.aggregate).?.data) |elem_val| {
if (!(try elem_val.compareWithZeroAdvanced(op, sema_kit))) return false;
if (!(try elem_val.compareAllWithZeroAdvanced(op, sema_kit))) return false;
}
return true;
},
Expand Down Expand Up @@ -2982,7 +2984,7 @@ pub const Value = extern union {
.int_i64,
.int_big_positive,
.int_big_negative,
=> compareWithZero(self, .eq),
=> compareAllWithZero(self, .eq),

.undef => unreachable,
.unreachable_value => unreachable,
Expand Down
5 changes: 5 additions & 0 deletions test/behavior.zig
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ test {
_ = @import("behavior/bugs/12003.zig");
_ = @import("behavior/bugs/12025.zig");
_ = @import("behavior/bugs/12033.zig");
_ = @import("behavior/bugs/12043.zig");
_ = @import("behavior/bugs/12430.zig");
_ = @import("behavior/bugs/12486.zig");
_ = @import("behavior/bugs/12488.zig");
Expand All @@ -104,7 +105,10 @@ test {
_ = @import("behavior/bugs/12945.zig");
_ = @import("behavior/bugs/12972.zig");
_ = @import("behavior/bugs/12984.zig");
_ = @import("behavior/bugs/13064.zig");
_ = @import("behavior/bugs/13065.zig");
_ = @import("behavior/bugs/13068.zig");
_ = @import("behavior/bugs/13069.zig");
_ = @import("behavior/bugs/13112.zig");
_ = @import("behavior/bugs/13128.zig");
_ = @import("behavior/bugs/13164.zig");
Expand Down Expand Up @@ -210,6 +214,7 @@ test {
builtin.zig_backend != .stage2_wasm and
builtin.zig_backend != .stage2_c)
{
_ = @import("behavior/bugs/13063.zig");
_ = @import("behavior/bugs/11227.zig");
_ = @import("behavior/export.zig");
}
Expand Down
12 changes: 12 additions & 0 deletions test/behavior/bugs/12043.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const std = @import("std");
const expect = std.testing.expect;

var ok = false;
fn foo(x: anytype) void {
ok = x;
}
test {
const x = &foo;
x(true);
try expect(ok);
}
16 changes: 16 additions & 0 deletions test/behavior/bugs/13063.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const std = @import("std");
const expect = std.testing.expect;

var pos = [2]f32{ 0.0, 0.0 };
test "store to global array" {
try expect(pos[1] == 0.0);
pos = [2]f32{ 0.0, 1.0 };
try expect(pos[1] == 1.0);
}

var vpos = @Vector(2, f32){ 0.0, 0.0 };
test "store to global vector" {
try expect(vpos[1] == 0.0);
vpos = @Vector(2, f32){ 0.0, 1.0 };
try expect(vpos[1] == 1.0);
}
17 changes: 17 additions & 0 deletions test/behavior/bugs/13064.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const std = @import("std");
const builtin = @import("builtin");
const expect = std.testing.expect;

test {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO

var x: [10][10]u32 = undefined;

x[0][1] = 0;
const a = x[0];
x[0][1] = 15;

try expect(a[1] == 0);
}
22 changes: 22 additions & 0 deletions test/behavior/bugs/13065.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const std = @import("std");
const builtin = @import("builtin");
const expect = std.testing.expect;

const U = union(enum) {
array: [10]u32,
other: u32,
};

test {
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO

var x = U{ .array = undefined };

x.array[1] = 0;
const a = x.array;
x.array[1] = 15;

try expect(a[1] == 0);
}
17 changes: 17 additions & 0 deletions test/behavior/bugs/13069.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const std = @import("std");
const builtin = @import("builtin");
const expect = std.testing.expect;

test {
if (builtin.zig_backend == .stage2_arm) 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
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO

var opt_x: ?[3]f32 = [_]f32{0.0} ** 3;

const x = opt_x.?;
opt_x.?[0] = 15.0;

try expect(x[0] == 0.0);
}
71 changes: 66 additions & 5 deletions test/behavior/vector.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1136,11 +1136,6 @@ test "array of vectors is copied" {
}

test "byte vector initialized in inline function" {
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
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO

const S = struct {
inline fn boolx4(e0: bool, e1: bool, e2: bool, e3: bool) @Vector(4, bool) {
return .{ e0, e1, e2, e3 };
Expand Down Expand Up @@ -1170,3 +1165,69 @@ test "byte vector initialized in inline function" {

try expect(S.all(S.boolx4(true, true, true, true)));
}

test "zero divisor" {
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
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO

const zeros = @Vector(2, f32){ 0.0, 0.0 };
const ones = @Vector(2, f32){ 1.0, 1.0 };

const v1 = zeros / ones;
const v2 = @divExact(zeros, ones);
const v3 = @divTrunc(zeros, ones);
const v4 = @divFloor(zeros, ones);

_ = v1[0];
_ = v2[0];
_ = v3[0];
_ = v4[0];
}

test "zero multiplicand" {
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_c) 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
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO

const zeros = @Vector(2, u32){ 0.0, 0.0 };
var ones = @Vector(2, u32){ 1.0, 1.0 };

_ = (ones * zeros)[0];
_ = (zeros * zeros)[0];
_ = (zeros * ones)[0];

_ = (ones *| zeros)[0];
_ = (zeros *| zeros)[0];
_ = (zeros *| ones)[0];

_ = (ones *% zeros)[0];
_ = (zeros *% zeros)[0];
_ = (zeros *% ones)[0];
}

test "@intCast to u0" {
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_c) 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
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO

var zeros = @Vector(2, u32){ 0, 0 };
const casted = @intCast(@Vector(2, u0), zeros);

_ = casted[0];
}

test "modRem with zero divisor" {
comptime {
var zeros = @Vector(2, u32){ 0, 0 };
const ones = @Vector(2, u32){ 1, 1 };

zeros %= ones;
_ = zeros[0];
}
}