ziglang / zig

General-purpose programming language and toolchain for maintaining robust, optimal, and reusable software.
https://ziglang.org
MIT License
34.04k stars 2.49k forks source link

proposal: remove type parameter from `@select` in favor of RLS #21523

Open xdBronch opened 6 days ago

xdBronch commented 6 days ago

the way @select currently works is a bit odd. from the langref the signature is this

@select(comptime T: type, pred: @Vector(len, bool), a: @Vector(len, T), b: @Vector(len, T)) @Vector(len, T)

there are 2 things wrong with this the way i see it. first the type parameter is a little clunky and somewhat redundant, this information can already be gotten from a, b, or the result type. second is len, its not explicitly given and used for all 3 params but its only resolved from the length of pred which makes certain code more cumbersome. a result location could possibly be provided for a and b with the current system but then that would the type param even more redundant and pred would exclusively not have one. current (possibly contrived :p) usage might look like this

fn foo(pred: @Vector(4, bool)) @Vector(4, u8) {
    // very messy, not nice to read or write and not consistent with many other builtins
    return @select(u8, pred, @as(@Vector(4, u8), @splat(12)), @as(@Vector(4, u8), @splat(32)));
}
fn bar(p1: bool, p2: bool, p3: bool, p4: bool) @Vector(4, u8) {
    return @select(
        u8,
        // this argument exclusively requires `@Vector` because it's where `len` is derived
        // meaning it has no result type at all while the others sorta kinda do?
        @Vector(4, bool){ p1, p2, p3, p4 },
        .{ 1, 2, 3, 4 },
        .{ 5, 6, 7, 8 },
    );
}

i propose to remove the type parameter and provide result locations to all the remaining parameters based on the result type, usage might look like this

fn foo(pred: @Vector(4, bool)) @Vector(4, u8) {
    return @select(pred, @splat(12), @splat(34));
}
fn bar(p1: bool, p2: bool, p3: bool, p4: bool) @Vector(4, u8) {
    return @select(
        // all arguments now have a result type and can use `.{` if needed
        .{ p1, p2, p3, p4 },
        .{ 1, 2, 3, 4 },
        .{ 5, 6, 7, 8 },
    );
}
xdBronch commented 6 days ago

bit of empirical evidence @Validark if youd like to give an opinion, you seem to be a heavy user of vectors and @select in particular. havent looked thru everything but it seems like a majority of your code in those issues using @select would benefit, tho im not sure if those are more pseudo code than not :p

Validark commented 6 days ago

bit of empirical evidence @Validark if youd like to give an opinion, you seem to be a heavy user of vectors and @select in particular. havent looked thru everything but it seems like a majority of your code in those issues using @select would benefit, tho im not sure if those are more pseudo code than not :p

Indeed, and I have given working code for basically every issue I've submitted to LLVM, usually based on real code that's been stripped down.

I do use @select a lot. I'd say it's one of the main things I type, actually. I'm definitely in favor of more vector RLS. It's really noisy having to type out vector types all the time, even when I abbreviate it with @as(V, @splat(0)) it gets a bit cumbersome at times. I'm always relieved when I do a vector shift and I can just rely on RLS without having to write the type every time.

ethernetsellout commented 6 days ago

Given that len and T can be inferred from the result type, it's surprising this hasn't been implemented alongside similar improvements to other builtins. Reducing friction for vectors is going to be beneficial in general. #17274 would also help.